Home | History | Annotate | Download | only in Driver
      1 //===--- SanitizerArgs.h - Arguments for sanitizer tools  -------*- C++ -*-===//
      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 #ifndef CLANG_LIB_DRIVER_SANITIZERARGS_H_
     10 #define CLANG_LIB_DRIVER_SANITIZERARGS_H_
     11 
     12 #include "llvm/Option/Arg.h"
     13 #include "llvm/Option/ArgList.h"
     14 #include <string>
     15 
     16 namespace clang {
     17 namespace driver {
     18 
     19 class Driver;
     20 class ToolChain;
     21 
     22 class SanitizerArgs {
     23   /// Assign ordinals to sanitizer flags. We'll use the ordinal values as
     24   /// bit positions within \c Kind.
     25   enum SanitizeOrdinal {
     26 #define SANITIZER(NAME, ID) SO_##ID,
     27 #define SANITIZER_GROUP(NAME, ID, ALIAS) SO_##ID##Group,
     28 #include "clang/Basic/Sanitizers.def"
     29     SO_Count
     30   };
     31 
     32   /// Bugs to catch at runtime.
     33   enum SanitizeKind {
     34 #define SANITIZER(NAME, ID) ID = 1 << SO_##ID,
     35 #define SANITIZER_GROUP(NAME, ID, ALIAS)                                       \
     36   ID = ALIAS, ID##Group = 1 << SO_##ID##Group,
     37 #include "clang/Basic/Sanitizers.def"
     38     NeedsAsanRt = Address,
     39     NeedsTsanRt = Thread,
     40     NeedsMsanRt = Memory,
     41     NeedsDfsanRt = DataFlow,
     42     NeedsLeakDetection = Leak,
     43     NeedsUbsanRt = Undefined | Integer,
     44     NotAllowedWithTrap = Vptr,
     45     HasZeroBaseShadow = Thread | Memory | DataFlow,
     46     NeedsUnwindTables = Address | Thread | Memory | DataFlow
     47   };
     48   unsigned Kind;
     49 
     50   std::string BlacklistFile;
     51   int MsanTrackOrigins;
     52   bool AsanZeroBaseShadow;
     53   bool UbsanTrapOnError;
     54   bool AsanSharedRuntime;
     55 
     56  public:
     57   SanitizerArgs();
     58   /// Parses the sanitizer arguments from an argument list.
     59   SanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args);
     60 
     61   bool needsAsanRt() const { return Kind & NeedsAsanRt; }
     62   bool needsSharedAsanRt() const { return AsanSharedRuntime; }
     63   bool needsTsanRt() const { return Kind & NeedsTsanRt; }
     64   bool needsMsanRt() const { return Kind & NeedsMsanRt; }
     65   bool needsLeakDetection() const { return Kind & NeedsLeakDetection; }
     66   bool needsLsanRt() const {
     67     return needsLeakDetection() && !needsAsanRt();
     68   }
     69   bool needsUbsanRt() const {
     70     return !UbsanTrapOnError && (Kind & NeedsUbsanRt);
     71   }
     72   bool needsDfsanRt() const { return Kind & NeedsDfsanRt; }
     73 
     74   bool sanitizesVptr() const { return Kind & Vptr; }
     75   bool notAllowedWithTrap() const { return Kind & NotAllowedWithTrap; }
     76   bool hasZeroBaseShadow() const {
     77     return (Kind & HasZeroBaseShadow) || AsanZeroBaseShadow;
     78   }
     79   bool needsUnwindTables() const { return Kind & NeedsUnwindTables; }
     80   void addArgs(const llvm::opt::ArgList &Args,
     81                llvm::opt::ArgStringList &CmdArgs) const;
     82 
     83  private:
     84   void clear();
     85 
     86   /// Parse a single value from a -fsanitize= or -fno-sanitize= value list.
     87   /// Returns OR of members of the \c SanitizeKind enumeration, or \c 0
     88   /// if \p Value is not known.
     89   static unsigned parse(const char *Value);
     90 
     91   /// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
     92   /// invalid components.
     93   static unsigned parse(const Driver &D, const llvm::opt::Arg *A,
     94                         bool DiagnoseErrors);
     95 
     96   /// Parse a single flag of the form -f[no]sanitize=, or
     97   /// -f*-sanitizer. Sets the masks defining required change of Kind value.
     98   /// Returns true if the flag was parsed successfully.
     99   static bool parse(const Driver &D, const llvm::opt::ArgList &Args,
    100                     const llvm::opt::Arg *A, unsigned &Add, unsigned &Remove,
    101                     bool DiagnoseErrors);
    102 
    103   /// Produce an argument string from ArgList \p Args, which shows how it
    104   /// provides a sanitizer kind in \p Mask. For example, the argument list
    105   /// "-fsanitize=thread,vptr -fsanitize=address" with mask \c NeedsUbsanRt
    106   /// would produce "-fsanitize=vptr".
    107   static std::string lastArgumentForKind(const Driver &D,
    108                                          const llvm::opt::ArgList &Args,
    109                                          unsigned Kind);
    110 
    111   /// Produce an argument string from argument \p A, which shows how it provides
    112   /// a value in \p Mask. For instance, the argument
    113   /// "-fsanitize=address,alignment" with mask \c NeedsUbsanRt would produce
    114   /// "-fsanitize=alignment".
    115   static std::string describeSanitizeArg(const llvm::opt::ArgList &Args,
    116                                          const llvm::opt::Arg *A,
    117                                          unsigned Mask);
    118 
    119   static bool getDefaultBlacklistForKind(const Driver &D, unsigned Kind,
    120                                          std::string &BLPath);
    121 
    122   /// Return the smallest superset of sanitizer set \p Kinds such that each
    123   /// member of each group whose flag is set in \p Kinds has its flag set in the
    124   /// result.
    125   static unsigned expandGroups(unsigned Kinds);
    126 
    127   /// Return the subset of \p Kinds supported by toolchain \p TC.  If
    128   /// \p DiagnoseErrors is true, produce an error diagnostic for each sanitizer
    129   /// removed from \p Kinds.
    130   static unsigned filterUnsupportedKinds(const ToolChain &TC, unsigned Kinds,
    131                                          const llvm::opt::ArgList &Args,
    132                                          const llvm::opt::Arg *A,
    133                                          bool DiagnoseErrors,
    134                                          unsigned &DiagnosedKinds);
    135 
    136   /// The flags in \p Mask are unsupported by \p TC.  If present in \p Kinds,
    137   /// remove them and produce an error diagnostic referring to \p A if
    138   /// \p DiagnoseErrors is true.
    139   static void filterUnsupportedMask(const ToolChain &TC, unsigned &Kinds,
    140                                     unsigned Mask,
    141                                     const llvm::opt::ArgList &Args,
    142                                     const llvm::opt::Arg *A,
    143                                     bool DiagnoseErrors,
    144                                     unsigned &DiagnosedKinds);
    145 };
    146 
    147 }  // namespace driver
    148 }  // namespace clang
    149 
    150 #endif // CLANG_LIB_DRIVER_SANITIZERARGS_H_
    151