clang  3.8.0
SanitizerArgs.cpp
Go to the documentation of this file.
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 //===----------------------------------------------------------------------===//
10 #include "Tools.h"
11 #include "clang/Basic/Sanitizers.h"
12 #include "clang/Driver/Driver.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,
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,
40  (Undefined & ~Vptr) | UnsignedIntegerOverflow | LocalBounds | CFI,
42 };
43 
45  CoverageFunc = 1 << 0,
46  CoverageBB = 1 << 1,
47  CoverageEdge = 1 << 2,
49  CoverageTraceBB = 1 << 4,
50  CoverageTraceCmp = 1 << 5,
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) {
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.
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 
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";
352  Arg->claim();
353  } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover)) {
354  DeprecatedReplacement = "-fno-sanitize-recover=undefined,integer";
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);
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) {
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 }
const llvm::Triple & getTriple() const
Definition: ToolChain.h:129
DiagnosticBuilder Diag(unsigned DiagID) const
Definition: Driver.h:90
virtual SanitizerMask getSupportedSanitizers() const
Return sanitizers which are available in this toolchain.
Definition: ToolChain.cpp:655
bool CCCIsCXX() const
Whether the driver should follow g++ like behavior.
Definition: Driver.h:151
Defines the clang::SanitizerKind enum.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
SanitizerMask Mask
Bitmask of enabled sanitizers.
Definition: Sanitizers.h:73
CoverageFeature
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition: Driver.h:65
const Driver & getDriver() const
Definition: ToolChain.h:127
detail::InMemoryDirectory::const_iterator I
virtual std::string getCompilerRT(const llvm::opt::ArgList &Args, StringRef Component, bool Shared=false) const
Definition: ToolChain.cpp:286
static SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A, bool DiagnoseErrors)
Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any invalid components.
static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A)
Parse -f(no-)?sanitize-coverage= flag values, diagnosing any invalid components.
Kind
const llvm::opt::Arg * getRTTIArg() const
Definition: ToolChain.h:155
virtual void clear()
RTTIMode getRTTIMode() const
Definition: ToolChain.h:158
uint64_t SanitizerMask
Definition: Sanitizers.h:24
std::unique_ptr< DiagnosticConsumer > create(StringRef OutputFile, DiagnosticOptions *Diags, bool MergeChildRecords=false)
Returns a DiagnosticConsumer that serializes diagnostics to a bitcode file.
detail::InMemoryDirectory::const_iterator E
SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups)
Parse a single value from a -fsanitize= or -fno-sanitize= value list.
Definition: Sanitizers.cpp:20
static SanitizerMask setGroupBits(SanitizerMask Kinds)
Sets group bits for every group that has at least one representative already enabled in Kinds...
bool isCXX(ID Id)
isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers).
Definition: Types.cpp:117
static bool getDefaultBlacklist(const Driver &D, SanitizerMask Kinds, std::string &BLPath)
bool isUsingLTO() const
Returns true if we are performing any kind of LTO.
Definition: Driver.h:421
SanitizerMask expandSanitizerGroups(SanitizerMask Kinds)
For each sanitizer group bit set in Kinds, set the bits for sanitizers this group enables...
Definition: Sanitizers.cpp:30
static SanitizerMask parseSanitizeTrapArgs(const Driver &D, const llvm::opt::ArgList &Args)
static std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask)
Produce an argument string from argument A, which shows how it provides a value in Mask...
static std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args, SanitizerMask Mask)
Produce an argument string from ArgList Args, which shows how it provides some sanitizer kind from Ma...
ToolChain - Access to tools for a single platform.
Definition: ToolChain.h:47
std::string ResourceDir
The path to the compiler resource directory.
Definition: Driver.h:110