1 //===--- SanitizerArgs.cpp - Arguments for sanitizer tools ---------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
9 #include "clang/Driver/SanitizerArgs.h"
10 #include "ToolChains/CommonArgs.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"
23 using namespace clang;
24 using namespace clang::SanitizerKind;
25 using namespace clang::driver;
26 using namespace llvm::opt;
28 enum : SanitizerMask {
29 NeedsUbsanRt = Undefined | Integer | Nullability | CFI,
30 NeedsUbsanCxxRt = Vptr | CFI,
31 NotAllowedWithTrap = Vptr,
32 RequiresPIE = DataFlow,
33 NeedsUnwindTables = Address | Thread | Memory | DataFlow,
35 Address | Memory | Leak | Undefined | Integer | Nullability | DataFlow,
36 RecoverableByDefault = Undefined | Integer | Nullability,
37 Unrecoverable = Unreachable | Return,
38 LegacyFsanitizeRecoverMask = Undefined | Integer,
40 TrappingSupported = (Undefined & ~Vptr) | UnsignedIntegerOverflow |
41 Nullability | LocalBounds | CFI,
42 TrappingDefault = CFI,
43 CFIClasses = CFIVCall | CFINVCall | CFIDerivedCast | CFIUnrelatedCast,
46 enum CoverageFeature {
47 CoverageFunc = 1 << 0,
49 CoverageEdge = 1 << 2,
50 CoverageIndirCall = 1 << 3,
51 CoverageTraceBB = 1 << 4,
52 CoverageTraceCmp = 1 << 5,
53 CoverageTraceDiv = 1 << 6,
54 CoverageTraceGep = 1 << 7,
55 Coverage8bitCounters = 1 << 8,
56 CoverageTracePC = 1 << 9,
57 CoverageTracePCGuard = 1 << 10,
60 /// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
61 /// invalid components. Returns a SanitizerMask.
62 static SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
65 /// Parse -f(no-)?sanitize-coverage= flag values, diagnosing any invalid
66 /// components. Returns OR of members of \c CoverageFeature enumeration.
67 static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A);
69 /// Produce an argument string from ArgList \p Args, which shows how it
70 /// provides some sanitizer kind from \p Mask. For example, the argument list
71 /// "-fsanitize=thread,vptr -fsanitize=address" with mask \c NeedsUbsanRt
72 /// would produce "-fsanitize=vptr".
73 static std::string lastArgumentForMask(const Driver &D,
74 const llvm::opt::ArgList &Args,
77 /// Produce an argument string from argument \p A, which shows how it provides
78 /// a value in \p Mask. For instance, the argument
79 /// "-fsanitize=address,alignment" with mask \c NeedsUbsanRt would produce
80 /// "-fsanitize=alignment".
81 static std::string describeSanitizeArg(const llvm::opt::Arg *A,
84 /// Produce a string containing comma-separated names of sanitizers in \p
86 static std::string toString(const clang::SanitizerSet &Sanitizers);
88 static bool getDefaultBlacklist(const Driver &D, SanitizerMask Kinds,
89 std::string &BLPath) {
90 const char *BlacklistFile = nullptr;
92 BlacklistFile = "asan_blacklist.txt";
93 else if (Kinds & Memory)
94 BlacklistFile = "msan_blacklist.txt";
95 else if (Kinds & Thread)
96 BlacklistFile = "tsan_blacklist.txt";
97 else if (Kinds & DataFlow)
98 BlacklistFile = "dfsan_abilist.txt";
100 BlacklistFile = "cfi_blacklist.txt";
103 clang::SmallString<64> Path(D.ResourceDir);
104 llvm::sys::path::append(Path, BlacklistFile);
111 /// Sets group bits for every group that has at least one representative already
112 /// enabled in \p Kinds.
113 static SanitizerMask setGroupBits(SanitizerMask Kinds) {
114 #define SANITIZER(NAME, ID)
115 #define SANITIZER_GROUP(NAME, ID, ALIAS) \
116 if (Kinds & SanitizerKind::ID) \
117 Kinds |= SanitizerKind::ID##Group;
118 #include "clang/Basic/Sanitizers.def"
122 static SanitizerMask parseSanitizeTrapArgs(const Driver &D,
123 const llvm::opt::ArgList &Args) {
124 SanitizerMask TrapRemove = 0; // During the loop below, the accumulated set of
125 // sanitizers disabled by the current sanitizer
126 // argument or any argument after it.
127 SanitizerMask TrappingKinds = 0;
128 SanitizerMask TrappingSupportedWithGroups = setGroupBits(TrappingSupported);
130 for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
132 const auto *Arg = *I;
133 if (Arg->getOption().matches(options::OPT_fsanitize_trap_EQ)) {
135 SanitizerMask Add = parseArgValues(D, Arg, true);
137 if (SanitizerMask InvalidValues = Add & ~TrappingSupportedWithGroups) {
139 S.Mask = InvalidValues;
140 D.Diag(diag::err_drv_unsupported_option_argument) << "-fsanitize-trap"
143 TrappingKinds |= expandSanitizerGroups(Add) & ~TrapRemove;
144 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) {
146 TrapRemove |= expandSanitizerGroups(parseArgValues(D, Arg, true));
147 } else if (Arg->getOption().matches(
148 options::OPT_fsanitize_undefined_trap_on_error)) {
151 expandSanitizerGroups(UndefinedGroup & ~TrapRemove) & ~TrapRemove;
152 } else if (Arg->getOption().matches(
153 options::OPT_fno_sanitize_undefined_trap_on_error)) {
155 TrapRemove |= expandSanitizerGroups(UndefinedGroup);
159 // Apply default trapping behavior.
160 TrappingKinds |= TrappingDefault & ~TrapRemove;
162 return TrappingKinds;
165 bool SanitizerArgs::needsUbsanRt() const {
166 return ((Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) ||
168 !Sanitizers.has(Address) && !Sanitizers.has(Memory) &&
169 !Sanitizers.has(Thread) && !Sanitizers.has(DataFlow) &&
170 !Sanitizers.has(Leak) && !CfiCrossDso;
173 bool SanitizerArgs::needsCfiRt() const {
174 return !(Sanitizers.Mask & CFI & ~TrapSanitizers.Mask) && CfiCrossDso;
177 bool SanitizerArgs::needsCfiDiagRt() const {
178 return (Sanitizers.Mask & CFI & ~TrapSanitizers.Mask) && CfiCrossDso;
181 bool SanitizerArgs::requiresPIE() const {
182 return NeedPIE || (Sanitizers.Mask & RequiresPIE);
185 bool SanitizerArgs::needsUnwindTables() const {
186 return Sanitizers.Mask & NeedsUnwindTables;
189 SanitizerArgs::SanitizerArgs(const ToolChain &TC,
190 const llvm::opt::ArgList &Args) {
191 SanitizerMask AllRemove = 0; // During the loop below, the accumulated set of
192 // sanitizers disabled by the current sanitizer
193 // argument or any argument after it.
194 SanitizerMask AllAddedKinds = 0; // Mask of all sanitizers ever enabled by
195 // -fsanitize= flags (directly or via group
196 // expansion), some of which may be disabled
197 // later. Used to carefully prune
198 // unused-argument diagnostics.
199 SanitizerMask DiagnosedKinds = 0; // All Kinds we have diagnosed up to now.
200 // Used to deduplicate diagnostics.
201 SanitizerMask Kinds = 0;
202 const SanitizerMask Supported = setGroupBits(TC.getSupportedSanitizers());
203 ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
205 const Driver &D = TC.getDriver();
206 SanitizerMask TrappingKinds = parseSanitizeTrapArgs(D, Args);
207 SanitizerMask InvalidTrappingKinds = TrappingKinds & NotAllowedWithTrap;
209 for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
211 const auto *Arg = *I;
212 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
214 SanitizerMask Add = parseArgValues(D, Arg, true);
215 AllAddedKinds |= expandSanitizerGroups(Add);
217 // Avoid diagnosing any sanitizer which is disabled later.
219 // At this point we have not expanded groups, so any unsupported
220 // sanitizers in Add are those which have been explicitly enabled.
222 if (SanitizerMask KindsToDiagnose =
223 Add & InvalidTrappingKinds & ~DiagnosedKinds) {
224 std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
225 D.Diag(diag::err_drv_argument_not_allowed_with)
226 << Desc << "-fsanitize-trap=undefined";
227 DiagnosedKinds |= KindsToDiagnose;
229 Add &= ~InvalidTrappingKinds;
230 if (SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
231 std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
232 D.Diag(diag::err_drv_unsupported_opt_for_target)
233 << Desc << TC.getTriple().str();
234 DiagnosedKinds |= KindsToDiagnose;
238 // Test for -fno-rtti + explicit -fsanitizer=vptr before expanding groups
239 // so we don't error out if -fno-rtti and -fsanitize=undefined were
242 (RTTIMode == ToolChain::RM_DisabledImplicitly ||
243 RTTIMode == ToolChain::RM_DisabledExplicitly)) {
244 if (RTTIMode == ToolChain::RM_DisabledImplicitly)
245 // Warn about not having rtti enabled if the vptr sanitizer is
246 // explicitly enabled
247 D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
249 const llvm::opt::Arg *NoRTTIArg = TC.getRTTIArg();
251 "RTTI disabled explicitly but we have no argument!");
252 D.Diag(diag::err_drv_argument_not_allowed_with)
253 << "-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
256 // Take out the Vptr sanitizer from the enabled sanitizers
260 Add = expandSanitizerGroups(Add);
261 // Group expansion may have enabled a sanitizer which is disabled later.
263 // Silently discard any unsupported sanitizers implicitly enabled through
265 Add &= ~InvalidTrappingKinds;
269 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
271 SanitizerMask Remove = parseArgValues(D, Arg, true);
272 AllRemove |= expandSanitizerGroups(Remove);
276 // Enable toolchain specific default sanitizers if not explicitly disabled.
277 Kinds |= TC.getDefaultSanitizers() & ~AllRemove;
279 // We disable the vptr sanitizer if it was enabled by group expansion but RTTI
281 if ((Kinds & Vptr) &&
282 (RTTIMode == ToolChain::RM_DisabledImplicitly ||
283 RTTIMode == ToolChain::RM_DisabledExplicitly)) {
287 // Check that LTO is enabled if we need it.
288 if ((Kinds & NeedsLTO) && !D.isUsingLTO()) {
289 D.Diag(diag::err_drv_argument_only_allowed_with)
290 << lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto";
293 // Report error if there are non-trapping sanitizers that require
294 // c++abi-specific parts of UBSan runtime, and they are not provided by the
295 // toolchain. We don't have a good way to check the latter, so we just
296 // check if the toolchan supports vptr.
297 if (~Supported & Vptr) {
298 SanitizerMask KindsToDiagnose = Kinds & ~TrappingKinds & NeedsUbsanCxxRt;
299 // The runtime library supports the Microsoft C++ ABI, but only well enough
300 // for CFI. FIXME: Remove this once we support vptr on Windows.
301 if (TC.getTriple().isOSWindows())
302 KindsToDiagnose &= ~CFI;
303 if (KindsToDiagnose) {
305 S.Mask = KindsToDiagnose;
306 D.Diag(diag::err_drv_unsupported_opt_for_target)
307 << ("-fno-sanitize-trap=" + toString(S)) << TC.getTriple().str();
308 Kinds &= ~KindsToDiagnose;
312 // Warn about incompatible groups of sanitizers.
313 std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
314 std::make_pair(Address, Thread), std::make_pair(Address, Memory),
315 std::make_pair(Thread, Memory), std::make_pair(Leak, Thread),
316 std::make_pair(Leak, Memory), std::make_pair(KernelAddress, Address),
317 std::make_pair(KernelAddress, Leak),
318 std::make_pair(KernelAddress, Thread),
319 std::make_pair(KernelAddress, Memory),
320 std::make_pair(Efficiency, Address),
321 std::make_pair(Efficiency, Leak),
322 std::make_pair(Efficiency, Thread),
323 std::make_pair(Efficiency, Memory),
324 std::make_pair(Efficiency, KernelAddress)};
325 for (auto G : IncompatibleGroups) {
326 SanitizerMask Group = G.first;
328 if (SanitizerMask Incompatible = Kinds & G.second) {
329 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
330 << lastArgumentForMask(D, Args, Group)
331 << lastArgumentForMask(D, Args, Incompatible);
332 Kinds &= ~Incompatible;
336 // FIXME: Currently -fsanitize=leak is silently ignored in the presence of
337 // -fsanitize=address. Perhaps it should print an error, or perhaps
338 // -f(-no)sanitize=leak should change whether leak detection is enabled by
341 // Parse -f(no-)?sanitize-recover flags.
342 SanitizerMask RecoverableKinds = RecoverableByDefault;
343 SanitizerMask DiagnosedUnrecoverableKinds = 0;
344 for (const auto *Arg : Args) {
345 const char *DeprecatedReplacement = nullptr;
346 if (Arg->getOption().matches(options::OPT_fsanitize_recover)) {
347 DeprecatedReplacement =
348 "-fsanitize-recover=undefined,integer' or '-fsanitize-recover=all";
349 RecoverableKinds |= expandSanitizerGroups(LegacyFsanitizeRecoverMask);
351 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover)) {
352 DeprecatedReplacement = "-fno-sanitize-recover=undefined,integer' or "
353 "'-fno-sanitize-recover=all";
354 RecoverableKinds &= ~expandSanitizerGroups(LegacyFsanitizeRecoverMask);
356 } else if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
357 SanitizerMask Add = parseArgValues(D, Arg, true);
358 // Report error if user explicitly tries to recover from unrecoverable
360 if (SanitizerMask KindsToDiagnose =
361 Add & Unrecoverable & ~DiagnosedUnrecoverableKinds) {
362 SanitizerSet SetToDiagnose;
363 SetToDiagnose.Mask |= KindsToDiagnose;
364 D.Diag(diag::err_drv_unsupported_option_argument)
365 << Arg->getOption().getName() << toString(SetToDiagnose);
366 DiagnosedUnrecoverableKinds |= KindsToDiagnose;
368 RecoverableKinds |= expandSanitizerGroups(Add);
370 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {
371 RecoverableKinds &= ~expandSanitizerGroups(parseArgValues(D, Arg, true));
374 if (DeprecatedReplacement) {
375 D.Diag(diag::warn_drv_deprecated_arg) << Arg->getAsString(Args)
376 << DeprecatedReplacement;
379 RecoverableKinds &= Kinds;
380 RecoverableKinds &= ~Unrecoverable;
382 TrappingKinds &= Kinds;
384 // Setup blacklist files.
385 // Add default blacklist from resource directory.
388 if (getDefaultBlacklist(D, Kinds, BLPath) && llvm::sys::fs::exists(BLPath))
389 BlacklistFiles.push_back(BLPath);
391 // Parse -f(no-)sanitize-blacklist options.
392 for (const auto *Arg : Args) {
393 if (Arg->getOption().matches(options::OPT_fsanitize_blacklist)) {
395 std::string BLPath = Arg->getValue();
396 if (llvm::sys::fs::exists(BLPath)) {
397 BlacklistFiles.push_back(BLPath);
398 ExtraDeps.push_back(BLPath);
400 D.Diag(clang::diag::err_drv_no_such_file) << BLPath;
402 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_blacklist)) {
404 BlacklistFiles.clear();
408 // Validate blacklists format.
411 std::unique_ptr<llvm::SpecialCaseList> SCL(
412 llvm::SpecialCaseList::create(BlacklistFiles, BLError));
414 D.Diag(clang::diag::err_drv_malformed_sanitizer_blacklist) << BLError;
417 // Parse -f[no-]sanitize-memory-track-origins[=level] options.
418 if (AllAddedKinds & Memory) {
420 Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
421 options::OPT_fsanitize_memory_track_origins,
422 options::OPT_fno_sanitize_memory_track_origins)) {
423 if (A->getOption().matches(options::OPT_fsanitize_memory_track_origins)) {
424 MsanTrackOrigins = 2;
425 } else if (A->getOption().matches(
426 options::OPT_fno_sanitize_memory_track_origins)) {
427 MsanTrackOrigins = 0;
429 StringRef S = A->getValue();
430 if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
431 MsanTrackOrigins > 2) {
432 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
437 Args.hasArg(options::OPT_fsanitize_memory_use_after_dtor);
438 NeedPIE |= !(TC.getTriple().isOSLinux() &&
439 TC.getTriple().getArch() == llvm::Triple::x86_64);
442 if (AllAddedKinds & Thread) {
443 TsanMemoryAccess = Args.hasFlag(options::OPT_fsanitize_thread_memory_access,
444 options::OPT_fno_sanitize_thread_memory_access,
446 TsanFuncEntryExit = Args.hasFlag(options::OPT_fsanitize_thread_func_entry_exit,
447 options::OPT_fno_sanitize_thread_func_entry_exit,
449 TsanAtomics = Args.hasFlag(options::OPT_fsanitize_thread_atomics,
450 options::OPT_fno_sanitize_thread_atomics,
454 if (AllAddedKinds & CFI) {
455 CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
456 options::OPT_fno_sanitize_cfi_cross_dso, false);
457 // Without PIE, external function address may resolve to a PLT record, which
458 // can not be verified by the target module.
459 NeedPIE |= CfiCrossDso;
462 Stats = Args.hasFlag(options::OPT_fsanitize_stats,
463 options::OPT_fno_sanitize_stats, false);
465 // Parse -f(no-)?sanitize-coverage flags if coverage is supported by the
466 // enabled sanitizers.
467 for (const auto *Arg : Args) {
468 if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
469 int LegacySanitizeCoverage;
470 if (Arg->getNumValues() == 1 &&
471 !StringRef(Arg->getValue(0))
472 .getAsInteger(0, LegacySanitizeCoverage) &&
473 LegacySanitizeCoverage >= 0 && LegacySanitizeCoverage <= 4) {
474 switch (LegacySanitizeCoverage) {
476 CoverageFeatures = 0;
480 D.Diag(diag::warn_drv_deprecated_arg) << Arg->getAsString(Args)
481 << "-fsanitize-coverage=func";
482 CoverageFeatures = CoverageFunc;
485 D.Diag(diag::warn_drv_deprecated_arg) << Arg->getAsString(Args)
486 << "-fsanitize-coverage=bb";
487 CoverageFeatures = CoverageBB;
490 D.Diag(diag::warn_drv_deprecated_arg) << Arg->getAsString(Args)
491 << "-fsanitize-coverage=edge";
492 CoverageFeatures = CoverageEdge;
495 D.Diag(diag::warn_drv_deprecated_arg)
496 << Arg->getAsString(Args)
497 << "-fsanitize-coverage=edge,indirect-calls";
498 CoverageFeatures = CoverageEdge | CoverageIndirCall;
503 CoverageFeatures |= parseCoverageFeatures(D, Arg);
505 // Disable coverage and not claim the flags if there is at least one
506 // non-supporting sanitizer.
507 if (!(AllAddedKinds & ~setGroupBits(SupportsCoverage))) {
510 CoverageFeatures = 0;
512 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
514 CoverageFeatures &= ~parseCoverageFeatures(D, Arg);
517 // Choose at most one coverage type: function, bb, or edge.
518 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageBB))
519 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
520 << "-fsanitize-coverage=func"
521 << "-fsanitize-coverage=bb";
522 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageEdge))
523 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
524 << "-fsanitize-coverage=func"
525 << "-fsanitize-coverage=edge";
526 if ((CoverageFeatures & CoverageBB) && (CoverageFeatures & CoverageEdge))
527 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
528 << "-fsanitize-coverage=bb"
529 << "-fsanitize-coverage=edge";
530 // Basic block tracing and 8-bit counters require some type of coverage
532 int CoverageTypes = CoverageFunc | CoverageBB | CoverageEdge;
533 if ((CoverageFeatures & CoverageTraceBB) &&
534 !(CoverageFeatures & CoverageTypes))
535 D.Diag(clang::diag::err_drv_argument_only_allowed_with)
536 << "-fsanitize-coverage=trace-bb"
537 << "-fsanitize-coverage=(func|bb|edge)";
538 if ((CoverageFeatures & Coverage8bitCounters) &&
539 !(CoverageFeatures & CoverageTypes))
540 D.Diag(clang::diag::err_drv_argument_only_allowed_with)
541 << "-fsanitize-coverage=8bit-counters"
542 << "-fsanitize-coverage=(func|bb|edge)";
543 // trace-pc w/o func/bb/edge implies edge.
544 if ((CoverageFeatures & (CoverageTracePC | CoverageTracePCGuard)) &&
545 !(CoverageFeatures & CoverageTypes))
546 CoverageFeatures |= CoverageEdge;
548 if (AllAddedKinds & Address) {
550 Args.hasArg(options::OPT_shared_libasan) || TC.getTriple().isAndroid();
551 NeedPIE |= TC.getTriple().isAndroid();
553 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
554 StringRef S = A->getValue();
555 // Legal values are 0 and 1, 2, but in future we may add more levels.
556 if (S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
557 AsanFieldPadding > 2) {
558 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
562 if (Arg *WindowsDebugRTArg =
563 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
564 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
565 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
566 switch (WindowsDebugRTArg->getOption().getID()) {
567 case options::OPT__SLASH_MTd:
568 case options::OPT__SLASH_MDd:
569 case options::OPT__SLASH_LDd:
570 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
571 << WindowsDebugRTArg->getAsString(Args)
572 << lastArgumentForMask(D, Args, Address);
573 D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
577 if (Arg *A = Args.getLastArg(
578 options::OPT_fsanitize_address_use_after_scope,
579 options::OPT_fno_sanitize_address_use_after_scope)) {
580 AsanUseAfterScope = A->getOption().getID() ==
581 options::OPT_fsanitize_address_use_after_scope;
585 // Parse -link-cxx-sanitizer flag.
587 Args.hasArg(options::OPT_fsanitize_link_cxx_runtime) || D.CCCIsCXX();
589 // Finally, initialize the set of available and recoverable sanitizers.
590 Sanitizers.Mask |= Kinds;
591 RecoverableSanitizers.Mask |= RecoverableKinds;
592 TrapSanitizers.Mask |= TrappingKinds;
595 static std::string toString(const clang::SanitizerSet &Sanitizers) {
597 #define SANITIZER(NAME, ID) \
598 if (Sanitizers.has(ID)) { \
603 #include "clang/Basic/Sanitizers.def"
607 static void addIncludeLinkerOption(const ToolChain &TC,
608 const llvm::opt::ArgList &Args,
609 llvm::opt::ArgStringList &CmdArgs,
610 StringRef SymbolName) {
611 SmallString<64> LinkerOptionFlag;
612 LinkerOptionFlag = "--linker-option=/include:";
613 if (TC.getTriple().getArch() == llvm::Triple::x86) {
614 // Win32 mangles C function names with a '_' prefix.
615 LinkerOptionFlag += '_';
617 LinkerOptionFlag += SymbolName;
618 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
621 void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
622 llvm::opt::ArgStringList &CmdArgs,
623 types::ID InputType) const {
624 // NVPTX doesn't currently support sanitizers. Bailing out here means that
625 // e.g. -fsanitize=address applies only to host code, which is what we want
627 if (TC.getTriple().isNVPTX())
630 // Translate available CoverageFeatures to corresponding clang-cc1 flags.
631 // Do it even if Sanitizers.empty() since some forms of coverage don't require
633 std::pair<int, const char *> CoverageFlags[] = {
634 std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"),
635 std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"),
636 std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"),
637 std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"),
638 std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"),
639 std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"),
640 std::make_pair(CoverageTraceDiv, "-fsanitize-coverage-trace-div"),
641 std::make_pair(CoverageTraceGep, "-fsanitize-coverage-trace-gep"),
642 std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"),
643 std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"),
644 std::make_pair(CoverageTracePCGuard, "-fsanitize-coverage-trace-pc-guard")};
645 for (auto F : CoverageFlags) {
646 if (CoverageFeatures & F.first)
647 CmdArgs.push_back(Args.MakeArgString(F.second));
650 if (TC.getTriple().isOSWindows() && needsUbsanRt()) {
651 // Instruct the code generator to embed linker directives in the object file
652 // that cause the required runtime libraries to be linked.
653 CmdArgs.push_back(Args.MakeArgString(
654 "--dependent-lib=" + TC.getCompilerRT(Args, "ubsan_standalone")));
655 if (types::isCXX(InputType))
656 CmdArgs.push_back(Args.MakeArgString(
657 "--dependent-lib=" + TC.getCompilerRT(Args, "ubsan_standalone_cxx")));
659 if (TC.getTriple().isOSWindows() && needsStatsRt()) {
660 CmdArgs.push_back(Args.MakeArgString("--dependent-lib=" +
661 TC.getCompilerRT(Args, "stats_client")));
663 // The main executable must export the stats runtime.
664 // FIXME: Only exporting from the main executable (e.g. based on whether the
665 // translation unit defines main()) would save a little space, but having
666 // multiple copies of the runtime shouldn't hurt.
667 CmdArgs.push_back(Args.MakeArgString("--dependent-lib=" +
668 TC.getCompilerRT(Args, "stats")));
669 addIncludeLinkerOption(TC, Args, CmdArgs, "__sanitizer_stats_register");
672 if (Sanitizers.empty())
674 CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers)));
676 if (!RecoverableSanitizers.empty())
677 CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" +
678 toString(RecoverableSanitizers)));
680 if (!TrapSanitizers.empty())
682 Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));
684 for (const auto &BLPath : BlacklistFiles) {
685 SmallString<64> BlacklistOpt("-fsanitize-blacklist=");
686 BlacklistOpt += BLPath;
687 CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
689 for (const auto &Dep : ExtraDeps) {
690 SmallString<64> ExtraDepOpt("-fdepfile-entry=");
692 CmdArgs.push_back(Args.MakeArgString(ExtraDepOpt));
695 if (MsanTrackOrigins)
696 CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" +
697 llvm::utostr(MsanTrackOrigins)));
699 if (MsanUseAfterDtor)
700 CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-use-after-dtor"));
702 // FIXME: Pass these parameters as function attributes, not as -llvm flags.
703 if (!TsanMemoryAccess) {
704 CmdArgs.push_back("-mllvm");
705 CmdArgs.push_back("-tsan-instrument-memory-accesses=0");
706 CmdArgs.push_back("-mllvm");
707 CmdArgs.push_back("-tsan-instrument-memintrinsics=0");
709 if (!TsanFuncEntryExit) {
710 CmdArgs.push_back("-mllvm");
711 CmdArgs.push_back("-tsan-instrument-func-entry-exit=0");
714 CmdArgs.push_back("-mllvm");
715 CmdArgs.push_back("-tsan-instrument-atomics=0");
719 CmdArgs.push_back(Args.MakeArgString("-fsanitize-cfi-cross-dso"));
722 CmdArgs.push_back(Args.MakeArgString("-fsanitize-stats"));
724 if (AsanFieldPadding)
725 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" +
726 llvm::utostr(AsanFieldPadding)));
728 if (AsanUseAfterScope)
729 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-use-after-scope"));
731 // MSan: Workaround for PR16386.
732 // ASan: This is mainly to help LSan with cases such as
733 // https://code.google.com/p/address-sanitizer/issues/detail?id=373
734 // We can't make this conditional on -fsanitize=leak, as that flag shouldn't
735 // affect compilation.
736 if (Sanitizers.has(Memory) || Sanitizers.has(Address))
737 CmdArgs.push_back(Args.MakeArgString("-fno-assume-sane-operator-new"));
739 // Require -fvisibility= flag on non-Windows when compiling if vptr CFI is
741 if (Sanitizers.hasOneOf(CFIClasses) && !TC.getTriple().isOSWindows() &&
742 !Args.hasArg(options::OPT_fvisibility_EQ)) {
743 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)
744 << lastArgumentForMask(TC.getDriver(), Args,
745 Sanitizers.Mask & CFIClasses)
750 SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
751 bool DiagnoseErrors) {
752 assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
753 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
754 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
755 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
756 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
757 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) &&
758 "Invalid argument in parseArgValues!");
759 SanitizerMask Kinds = 0;
760 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
761 const char *Value = A->getValue(i);
763 // Special case: don't accept -fsanitize=all.
764 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
765 0 == strcmp("all", Value))
767 // Similarly, don't accept -fsanitize=efficiency-all.
768 else if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
769 0 == strcmp("efficiency-all", Value))
772 Kind = parseSanitizerValue(Value, /*AllowGroups=*/true);
776 else if (DiagnoseErrors)
777 D.Diag(clang::diag::err_drv_unsupported_option_argument)
778 << A->getOption().getName() << Value;
783 int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A) {
784 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
785 A->getOption().matches(options::OPT_fno_sanitize_coverage));
787 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
788 const char *Value = A->getValue(i);
789 int F = llvm::StringSwitch<int>(Value)
790 .Case("func", CoverageFunc)
791 .Case("bb", CoverageBB)
792 .Case("edge", CoverageEdge)
793 .Case("indirect-calls", CoverageIndirCall)
794 .Case("trace-bb", CoverageTraceBB)
795 .Case("trace-cmp", CoverageTraceCmp)
796 .Case("trace-div", CoverageTraceDiv)
797 .Case("trace-gep", CoverageTraceGep)
798 .Case("8bit-counters", Coverage8bitCounters)
799 .Case("trace-pc", CoverageTracePC)
800 .Case("trace-pc-guard", CoverageTracePCGuard)
803 D.Diag(clang::diag::err_drv_unsupported_option_argument)
804 << A->getOption().getName() << Value;
810 std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,
811 SanitizerMask Mask) {
812 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
815 const auto *Arg = *I;
816 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
817 SanitizerMask AddKinds =
818 expandSanitizerGroups(parseArgValues(D, Arg, false));
820 return describeSanitizeArg(Arg, Mask);
821 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
822 SanitizerMask RemoveKinds =
823 expandSanitizerGroups(parseArgValues(D, Arg, false));
824 Mask &= ~RemoveKinds;
827 llvm_unreachable("arg list didn't provide expected value");
830 std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask) {
831 assert(A->getOption().matches(options::OPT_fsanitize_EQ)
832 && "Invalid argument in describeSanitizerArg!");
834 std::string Sanitizers;
835 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
836 if (expandSanitizerGroups(
837 parseSanitizerValue(A->getValue(i), /*AllowGroups=*/true)) &
839 if (!Sanitizers.empty())
841 Sanitizers += A->getValue(i);
845 assert(!Sanitizers.empty() && "arg didn't provide expected value");
846 return "-fsanitize=" + Sanitizers;