15 #include "llvm/ADT/StringExtras.h" 16 #include "llvm/ADT/StringSwitch.h" 17 #include "llvm/Support/FileSystem.h" 18 #include "llvm/Support/Path.h" 19 #include "llvm/Support/SpecialCaseList.h" 20 #include "llvm/Support/TargetParser.h" 23 using namespace clang;
28 SanitizerKind::Undefined | SanitizerKind::Integer |
30 SanitizerKind::CFI | SanitizerKind::FloatDivideByZero;
32 SanitizerKind::Vptr | SanitizerKind::CFI;
37 SanitizerKind::DataFlow | SanitizerKind::HWAddress | SanitizerKind::Scudo;
39 SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Thread |
40 SanitizerKind::Memory | SanitizerKind::DataFlow;
42 SanitizerKind::Address | SanitizerKind::HWAddress |
43 SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |
44 SanitizerKind::MemTag | SanitizerKind::Memory |
45 SanitizerKind::KernelMemory | SanitizerKind::Leak |
46 SanitizerKind::Undefined | SanitizerKind::Integer |
48 SanitizerKind::DataFlow | SanitizerKind::Fuzzer |
49 SanitizerKind::FuzzerNoLink | SanitizerKind::FloatDivideByZero |
50 SanitizerKind::SafeStack | SanitizerKind::ShadowCallStack;
52 SanitizerKind::Undefined | SanitizerKind::Integer |
54 SanitizerKind::FloatDivideByZero;
56 SanitizerKind::Unreachable | SanitizerKind::Return;
58 SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress;
60 SanitizerKind::Undefined | SanitizerKind::Integer;
64 SanitizerKind::UnsignedIntegerOverflow | SanitizerKind::ImplicitConversion |
66 SanitizerKind::CFI | SanitizerKind::FloatDivideByZero;
69 SanitizerKind::CFIVCall | SanitizerKind::CFINVCall |
70 SanitizerKind::CFIMFCall | SanitizerKind::CFIDerivedCast |
71 SanitizerKind::CFIUnrelatedCast;
73 TrappingSupported | SanitizerKind::Scudo | SanitizerKind::ShadowCallStack;
107 const llvm::opt::ArgList &Args,
122 std::vector<std::string> &BlacklistFiles) {
126 } Blacklists[] = {{
"asan_blacklist.txt", SanitizerKind::Address},
127 {
"hwasan_blacklist.txt", SanitizerKind::HWAddress},
128 {
"memtag_blacklist.txt", SanitizerKind::MemTag},
129 {
"msan_blacklist.txt", SanitizerKind::Memory},
130 {
"tsan_blacklist.txt", SanitizerKind::Thread},
131 {
"dfsan_abilist.txt", SanitizerKind::DataFlow},
132 {
"cfi_blacklist.txt", SanitizerKind::CFI},
133 {
"ubsan_blacklist.txt",
134 SanitizerKind::Undefined | SanitizerKind::Integer |
136 SanitizerKind::FloatDivideByZero}};
138 for (
auto BL : Blacklists) {
139 if (!(Kinds & BL.Mask))
143 llvm::sys::path::append(Path,
"share", BL.File);
144 if (D.
getVFS().exists(Path))
145 BlacklistFiles.push_back(Path.str());
146 else if (BL.Mask == SanitizerKind::CFI)
149 D.
Diag(clang::diag::err_drv_no_such_file) << Path;
156 #define SANITIZER(NAME, ID) 157 #define SANITIZER_GROUP(NAME, ID, ALIAS) \ 158 if (Kinds & SanitizerKind::ID) \ 159 Kinds |= SanitizerKind::ID##Group; 160 #include "clang/Basic/Sanitizers.def" 165 const llvm::opt::ArgList &Args) {
172 for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
174 const auto *Arg = *I;
175 if (Arg->getOption().matches(options::OPT_fsanitize_trap_EQ)) {
179 if (
SanitizerMask InvalidValues = Add & ~TrappingSupportedWithGroups) {
181 S.
Mask = InvalidValues;
182 D.
Diag(diag::err_drv_unsupported_option_argument) <<
"-fsanitize-trap" 186 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) {
189 }
else if (Arg->getOption().matches(
190 options::OPT_fsanitize_undefined_trap_on_error)) {
195 }
else if (Arg->getOption().matches(
196 options::OPT_fno_sanitize_undefined_trap_on_error)) {
203 TrappingKinds |= TrappingDefault & ~TrapRemove;
205 return TrappingKinds;
210 if (needsAsanRt() || needsMsanRt() || needsHwasanRt() || needsTsanRt() ||
211 needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() ||
212 (needsScudoRt() && !requiresMinimalRuntime()))
215 return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) ||
220 return !(Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
221 CfiCrossDso && !ImplicitCfiRuntime;
225 return (Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
226 CfiCrossDso && !ImplicitCfiRuntime;
238 return static_cast<bool>(Sanitizers.Mask &
NeedsLTO);
242 const llvm::opt::ArgList &Args) {
256 CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
257 options::OPT_fno_sanitize_cfi_cross_dso,
false);
266 Args.hasFlag(options::OPT_fsanitize_minimal_runtime,
267 options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime);
270 Arg *OptLevel = Args.getLastArg(options::OPT_O_Group);
271 bool RemoveObjectSizeAtO0 =
272 !OptLevel || OptLevel->getOption().matches(options::OPT_O0);
274 for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
276 const auto *Arg = *I;
277 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
281 if (RemoveObjectSizeAtO0) {
282 AllRemove |= SanitizerKind::ObjectSize;
286 if (Add & SanitizerKind::ObjectSize)
287 D.
Diag(diag::warn_drv_object_size_disabled_O0)
288 << Arg->getAsString(Args);
299 Add & InvalidTrappingKinds & ~DiagnosedKinds) {
301 D.
Diag(diag::err_drv_argument_not_allowed_with)
302 << Desc <<
"-fsanitize-trap=undefined";
303 DiagnosedKinds |= KindsToDiagnose;
305 Add &= ~InvalidTrappingKinds;
307 if (MinimalRuntime) {
309 Add & NotAllowedWithMinimalRuntime & ~DiagnosedKinds) {
311 D.
Diag(diag::err_drv_argument_not_allowed_with)
312 << Desc <<
"-fsanitize-minimal-runtime";
313 DiagnosedKinds |= KindsToDiagnose;
315 Add &= ~NotAllowedWithMinimalRuntime;
328 if (CfiCrossDso && (Add & SanitizerKind::CFIMFCall & ~DiagnosedKinds)) {
329 D.
Diag(diag::err_drv_argument_not_allowed_with)
330 <<
"-fsanitize=cfi-mfcall" 331 <<
"-fsanitize-cfi-cross-dso";
333 DiagnosedKinds |= SanitizerKind::CFIMFCall;
336 if (
SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
338 D.
Diag(diag::err_drv_unsupported_opt_for_target)
340 DiagnosedKinds |= KindsToDiagnose;
348 if (
const llvm::opt::Arg *NoRTTIArg = TC.
getRTTIArg()) {
349 assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) &&
350 "RTTI disabled without -fno-rtti option?");
353 D.
Diag(diag::err_drv_argument_not_allowed_with)
354 <<
"-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
358 D.
Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
362 AllRemove |= SanitizerKind::Vptr;
370 Add &= ~InvalidTrappingKinds;
371 if (MinimalRuntime) {
372 Add &= ~NotAllowedWithMinimalRuntime;
378 if (Add & SanitizerKind::Fuzzer)
379 Add |= SanitizerKind::FuzzerNoLink;
382 if (Add & SanitizerKind::FuzzerNoLink) {
391 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
398 std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
399 std::make_pair(SanitizerKind::Address,
400 SanitizerKind::Thread | SanitizerKind::Memory),
401 std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory),
402 std::make_pair(SanitizerKind::Leak,
403 SanitizerKind::Thread | SanitizerKind::Memory),
404 std::make_pair(SanitizerKind::KernelAddress,
405 SanitizerKind::Address | SanitizerKind::Leak |
406 SanitizerKind::Thread | SanitizerKind::Memory),
407 std::make_pair(SanitizerKind::HWAddress,
408 SanitizerKind::Address | SanitizerKind::Thread |
409 SanitizerKind::Memory | SanitizerKind::KernelAddress),
410 std::make_pair(SanitizerKind::Scudo,
411 SanitizerKind::Address | SanitizerKind::HWAddress |
412 SanitizerKind::Leak | SanitizerKind::Thread |
413 SanitizerKind::Memory | SanitizerKind::KernelAddress),
414 std::make_pair(SanitizerKind::SafeStack,
415 SanitizerKind::Address | SanitizerKind::HWAddress |
416 SanitizerKind::Leak | SanitizerKind::Thread |
417 SanitizerKind::Memory | SanitizerKind::KernelAddress),
418 std::make_pair(SanitizerKind::KernelHWAddress,
419 SanitizerKind::Address | SanitizerKind::HWAddress |
420 SanitizerKind::Leak | SanitizerKind::Thread |
421 SanitizerKind::Memory | SanitizerKind::KernelAddress |
422 SanitizerKind::SafeStack),
423 std::make_pair(SanitizerKind::KernelMemory,
424 SanitizerKind::Address | SanitizerKind::HWAddress |
425 SanitizerKind::Leak | SanitizerKind::Thread |
426 SanitizerKind::Memory | SanitizerKind::KernelAddress |
427 SanitizerKind::Scudo | SanitizerKind::SafeStack),
428 std::make_pair(SanitizerKind::MemTag,
429 SanitizerKind::Address | SanitizerKind::KernelAddress |
430 SanitizerKind::HWAddress |
431 SanitizerKind::KernelHWAddress)};
437 for (
auto G : IncompatibleGroups) {
439 if ((Default & Group) && (Kinds & G.second))
453 D.
Diag(diag::err_drv_argument_only_allowed_with)
457 if ((Kinds & SanitizerKind::ShadowCallStack) &&
458 TC.
getTriple().getArch() == llvm::Triple::aarch64 &&
459 !llvm::AArch64::isX18ReservedByDefault(TC.
getTriple()) &&
460 !Args.hasArg(options::OPT_ffixed_x18)) {
461 D.
Diag(diag::err_drv_argument_only_allowed_with)
470 if (~Supported & SanitizerKind::Vptr) {
475 KindsToDiagnose &= ~SanitizerKind::CFI;
476 if (KindsToDiagnose) {
478 S.
Mask = KindsToDiagnose;
479 D.
Diag(diag::err_drv_unsupported_opt_for_target)
481 Kinds &= ~KindsToDiagnose;
486 for (
auto G : IncompatibleGroups) {
490 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
493 Kinds &= ~Incompatible;
506 for (
const auto *Arg : Args) {
507 const char *DeprecatedReplacement =
nullptr;
508 if (Arg->getOption().matches(options::OPT_fsanitize_recover)) {
509 DeprecatedReplacement =
510 "-fsanitize-recover=undefined,integer' or '-fsanitize-recover=all";
513 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover)) {
514 DeprecatedReplacement =
"-fno-sanitize-recover=undefined,integer' or " 515 "'-fno-sanitize-recover=all";
518 }
else if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
523 Add & Unrecoverable & ~DiagnosedUnrecoverableKinds) {
525 SetToDiagnose.
Mask |= KindsToDiagnose;
526 D.
Diag(diag::err_drv_unsupported_option_argument)
527 << Arg->getOption().getName() <<
toString(SetToDiagnose);
528 DiagnosedUnrecoverableKinds |= KindsToDiagnose;
532 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {
537 Remove & AlwaysRecoverable & ~DiagnosedAlwaysRecoverableKinds) {
539 SetToDiagnose.
Mask |= KindsToDiagnose;
540 D.
Diag(diag::err_drv_unsupported_option_argument)
541 << Arg->getOption().getName() <<
toString(SetToDiagnose);
542 DiagnosedAlwaysRecoverableKinds |= KindsToDiagnose;
547 if (DeprecatedReplacement) {
548 D.
Diag(diag::warn_drv_deprecated_arg) << Arg->getAsString(Args)
549 << DeprecatedReplacement;
552 RecoverableKinds &= Kinds;
553 RecoverableKinds &= ~Unrecoverable;
555 TrappingKinds &= Kinds;
556 RecoverableKinds &= ~TrappingKinds;
562 for (
const auto *Arg : Args) {
563 if (Arg->getOption().matches(options::OPT_fsanitize_blacklist)) {
565 std::string BLPath = Arg->getValue();
566 if (D.
getVFS().exists(BLPath)) {
567 UserBlacklistFiles.push_back(BLPath);
569 D.
Diag(clang::diag::err_drv_no_such_file) << BLPath;
571 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_blacklist)) {
573 UserBlacklistFiles.clear();
574 SystemBlacklistFiles.clear();
580 std::unique_ptr<llvm::SpecialCaseList> SCL(
583 D.
Diag(clang::diag::err_drv_malformed_sanitizer_blacklist) << BLError;
588 SystemBlacklistFiles, D.
getVFS(), BLError));
590 D.
Diag(clang::diag::err_drv_malformed_sanitizer_blacklist) << BLError;
594 if (AllAddedKinds & SanitizerKind::Memory) {
596 Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
597 options::OPT_fsanitize_memory_track_origins,
598 options::OPT_fno_sanitize_memory_track_origins)) {
599 if (A->getOption().matches(options::OPT_fsanitize_memory_track_origins)) {
600 MsanTrackOrigins = 2;
601 }
else if (A->getOption().matches(
602 options::OPT_fno_sanitize_memory_track_origins)) {
603 MsanTrackOrigins = 0;
605 StringRef S = A->getValue();
606 if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
607 MsanTrackOrigins > 2) {
608 D.
Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
613 Args.hasFlag(options::OPT_fsanitize_memory_use_after_dtor,
614 options::OPT_fno_sanitize_memory_use_after_dtor,
616 NeedPIE |= !(TC.
getTriple().isOSLinux() &&
617 TC.
getTriple().getArch() == llvm::Triple::x86_64);
619 MsanUseAfterDtor =
false;
622 if (AllAddedKinds & SanitizerKind::Thread) {
623 TsanMemoryAccess = Args.hasFlag(
624 options::OPT_fsanitize_thread_memory_access,
625 options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess);
626 TsanFuncEntryExit = Args.hasFlag(
627 options::OPT_fsanitize_thread_func_entry_exit,
628 options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit);
630 Args.hasFlag(options::OPT_fsanitize_thread_atomics,
631 options::OPT_fno_sanitize_thread_atomics, TsanAtomics);
634 if (AllAddedKinds & SanitizerKind::CFI) {
637 NeedPIE |= CfiCrossDso;
638 CfiICallGeneralizePointers =
639 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
641 if (CfiCrossDso && CfiICallGeneralizePointers)
642 D.
Diag(diag::err_drv_argument_not_allowed_with)
643 <<
"-fsanitize-cfi-cross-dso" 644 <<
"-fsanitize-cfi-icall-generalize-pointers";
646 CfiCanonicalJumpTables =
647 Args.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables,
648 options::OPT_fno_sanitize_cfi_canonical_jump_tables,
true);
651 Stats = Args.hasFlag(options::OPT_fsanitize_stats,
652 options::OPT_fno_sanitize_stats,
false);
654 if (MinimalRuntime) {
657 if (IncompatibleMask)
658 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
659 <<
"-fsanitize-minimal-runtime" 662 SanitizerMask NonTrappingCfi = Kinds & SanitizerKind::CFI & ~TrappingKinds;
664 D.
Diag(clang::diag::err_drv_argument_only_allowed_with)
665 <<
"fsanitize-minimal-runtime" 666 <<
"fsanitize-trap=cfi";
671 for (
const auto *Arg : Args) {
672 if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
673 int LegacySanitizeCoverage;
674 if (Arg->getNumValues() == 1 &&
675 !StringRef(Arg->getValue(0))
676 .getAsInteger(0, LegacySanitizeCoverage)) {
677 CoverageFeatures = 0;
679 if (LegacySanitizeCoverage != 0) {
680 D.
Diag(diag::warn_drv_deprecated_arg)
681 << Arg->getAsString(Args) <<
"-fsanitize-coverage=trace-pc-guard";
689 if (!(AllAddedKinds & ~AllRemove & ~
setGroupBits(SupportsCoverage))) {
692 CoverageFeatures = 0;
694 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
701 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
702 <<
"-fsanitize-coverage=func" 703 <<
"-fsanitize-coverage=bb";
704 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures &
CoverageEdge))
705 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
706 <<
"-fsanitize-coverage=func" 707 <<
"-fsanitize-coverage=edge";
708 if ((CoverageFeatures & CoverageBB) && (CoverageFeatures & CoverageEdge))
709 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
710 <<
"-fsanitize-coverage=bb" 711 <<
"-fsanitize-coverage=edge";
715 D.
Diag(clang::diag::warn_drv_deprecated_arg)
716 <<
"-fsanitize-coverage=trace-bb" 717 <<
"-fsanitize-coverage=trace-pc-guard";
719 D.
Diag(clang::diag::warn_drv_deprecated_arg)
720 <<
"-fsanitize-coverage=8bit-counters" 721 <<
"-fsanitize-coverage=trace-pc-guard";
723 int InsertionPointTypes = CoverageFunc | CoverageBB |
CoverageEdge;
724 int InstrumentationTypes =
726 if ((CoverageFeatures & InsertionPointTypes) &&
727 !(CoverageFeatures & InstrumentationTypes)) {
728 D.
Diag(clang::diag::warn_drv_deprecated_arg)
729 <<
"-fsanitize-coverage=[func|bb|edge]" 730 <<
"-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc]";
734 if (!(CoverageFeatures & InsertionPointTypes)) {
735 if (CoverageFeatures &
744 Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan,
748 ImplicitCfiRuntime = TC.
getTriple().isAndroid();
750 if (AllAddedKinds & SanitizerKind::Address) {
753 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
754 StringRef S = A->getValue();
756 if (S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
757 AsanFieldPadding > 2) {
758 D.
Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
762 if (Arg *WindowsDebugRTArg =
763 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
764 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
765 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
766 switch (WindowsDebugRTArg->getOption().getID()) {
767 case options::OPT__SLASH_MTd:
768 case options::OPT__SLASH_MDd:
769 case options::OPT__SLASH_LDd:
770 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
771 << WindowsDebugRTArg->getAsString(Args)
773 D.
Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
777 AsanUseAfterScope = Args.hasFlag(
778 options::OPT_fsanitize_address_use_after_scope,
779 options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);
781 AsanPoisonCustomArrayCookie = Args.hasFlag(
782 options::OPT_fsanitize_address_poison_custom_array_cookie,
783 options::OPT_fno_sanitize_address_poison_custom_array_cookie,
784 AsanPoisonCustomArrayCookie);
789 AsanGlobalsDeadStripping =
792 Args.hasArg(options::OPT_fsanitize_address_globals_dead_stripping);
794 AsanUseOdrIndicator =
795 Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
796 options::OPT_fno_sanitize_address_use_odr_indicator,
797 AsanUseOdrIndicator);
799 if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) {
800 AsanInvalidPointerCmp =
true;
803 if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) {
804 AsanInvalidPointerSub =
true;
808 AsanUseAfterScope =
false;
811 SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract;
812 if (AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) {
813 TC.
getDriver().
Diag(clang::diag::err_drv_argument_only_allowed_with)
815 SanitizerKind::PointerCompare |
816 SanitizerKind::PointerSubtract)
817 <<
"-fsanitize=address";
821 if (AllAddedKinds & SanitizerKind::HWAddress) {
822 if (Arg *HwasanAbiArg =
823 Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {
824 HwasanAbi = HwasanAbiArg->getValue();
825 if (HwasanAbi !=
"platform" && HwasanAbi !=
"interceptor")
826 D.
Diag(clang::diag::err_drv_invalid_value)
827 << HwasanAbiArg->getAsString(Args) << HwasanAbi;
829 HwasanAbi =
"interceptor";
833 if (AllAddedKinds & SanitizerKind::SafeStack) {
835 SafeStackRuntime = !TC.
getTriple().isOSFuchsia();
839 Args.hasFlag(options::OPT_fsanitize_link_runtime,
840 options::OPT_fno_sanitize_link_runtime, LinkRuntimes);
843 LinkCXXRuntimes = Args.hasArg(options::OPT_fsanitize_link_cxx_runtime,
844 options::OPT_fno_sanitize_link_cxx_runtime,
849 Sanitizers.Mask |= Kinds;
850 RecoverableSanitizers.Mask |= RecoverableKinds;
851 TrapSanitizers.Mask |= TrappingKinds;
852 assert(!(RecoverableKinds & TrappingKinds) &&
853 "Overlap between recoverable and trapping sanitizers");
858 #define SANITIZER(NAME, ID) \ 859 if (Sanitizers.has(SanitizerKind::ID)) { \ 864 #include "clang/Basic/Sanitizers.def" 869 const llvm::opt::ArgList &Args,
870 llvm::opt::ArgStringList &CmdArgs,
871 StringRef SymbolName) {
873 LinkerOptionFlag =
"--linker-option=/include:";
874 if (TC.
getTriple().getArch() == llvm::Triple::x86) {
876 LinkerOptionFlag +=
'_';
878 LinkerOptionFlag += SymbolName;
879 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
883 for (
auto Start = CmdArgs.begin(),
End = CmdArgs.end(); Start !=
End; ++Start) {
884 auto It = std::find(Start,
End, StringRef(
"+mte"));
887 if (It > Start && *std::prev(It) == StringRef(
"-target-feature"))
895 llvm::opt::ArgStringList &CmdArgs,
906 std::pair<int, const char *> CoverageFlags[] = {
907 std::make_pair(
CoverageFunc,
"-fsanitize-coverage-type=1"),
908 std::make_pair(
CoverageBB,
"-fsanitize-coverage-type=2"),
909 std::make_pair(
CoverageEdge,
"-fsanitize-coverage-type=3"),
922 for (
auto F : CoverageFlags) {
923 if (CoverageFeatures & F.first)
924 CmdArgs.push_back(F.second);
927 if (TC.
getTriple().isOSWindows() && needsUbsanRt()) {
930 CmdArgs.push_back(Args.MakeArgString(
931 "--dependent-lib=" + TC.
getCompilerRT(Args,
"ubsan_standalone")));
933 CmdArgs.push_back(Args.MakeArgString(
934 "--dependent-lib=" + TC.
getCompilerRT(Args,
"ubsan_standalone_cxx")));
936 if (TC.
getTriple().isOSWindows() && needsStatsRt()) {
937 CmdArgs.push_back(Args.MakeArgString(
"--dependent-lib=" +
944 CmdArgs.push_back(Args.MakeArgString(
"--dependent-lib=" +
949 if (Sanitizers.empty())
951 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize=" +
toString(Sanitizers)));
953 if (!RecoverableSanitizers.empty())
954 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-recover=" +
957 if (!TrapSanitizers.empty())
959 Args.MakeArgString(
"-fsanitize-trap=" +
toString(TrapSanitizers)));
961 for (
const auto &BLPath : UserBlacklistFiles) {
963 BlacklistOpt += BLPath;
964 CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
966 for (
const auto &BLPath : SystemBlacklistFiles) {
968 BlacklistOpt += BLPath;
969 CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
972 if (MsanTrackOrigins)
973 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-memory-track-origins=" +
974 Twine(MsanTrackOrigins)));
976 if (MsanUseAfterDtor)
977 CmdArgs.push_back(
"-fsanitize-memory-use-after-dtor");
980 if (!TsanMemoryAccess) {
981 CmdArgs.push_back(
"-mllvm");
982 CmdArgs.push_back(
"-tsan-instrument-memory-accesses=0");
983 CmdArgs.push_back(
"-mllvm");
984 CmdArgs.push_back(
"-tsan-instrument-memintrinsics=0");
986 if (!TsanFuncEntryExit) {
987 CmdArgs.push_back(
"-mllvm");
988 CmdArgs.push_back(
"-tsan-instrument-func-entry-exit=0");
991 CmdArgs.push_back(
"-mllvm");
992 CmdArgs.push_back(
"-tsan-instrument-atomics=0");
996 CmdArgs.push_back(
"-fsanitize-cfi-cross-dso");
998 if (CfiICallGeneralizePointers)
999 CmdArgs.push_back(
"-fsanitize-cfi-icall-generalize-pointers");
1001 if (CfiCanonicalJumpTables)
1002 CmdArgs.push_back(
"-fsanitize-cfi-canonical-jump-tables");
1005 CmdArgs.push_back(
"-fsanitize-stats");
1008 CmdArgs.push_back(
"-fsanitize-minimal-runtime");
1010 if (AsanFieldPadding)
1011 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-address-field-padding=" +
1012 Twine(AsanFieldPadding)));
1014 if (AsanUseAfterScope)
1015 CmdArgs.push_back(
"-fsanitize-address-use-after-scope");
1017 if (AsanPoisonCustomArrayCookie)
1018 CmdArgs.push_back(
"-fsanitize-address-poison-custom-array-cookie");
1020 if (AsanGlobalsDeadStripping)
1021 CmdArgs.push_back(
"-fsanitize-address-globals-dead-stripping");
1023 if (AsanUseOdrIndicator)
1024 CmdArgs.push_back(
"-fsanitize-address-use-odr-indicator");
1026 if (AsanInvalidPointerCmp) {
1027 CmdArgs.push_back(
"-mllvm");
1028 CmdArgs.push_back(
"-asan-detect-invalid-pointer-cmp");
1031 if (AsanInvalidPointerSub) {
1032 CmdArgs.push_back(
"-mllvm");
1033 CmdArgs.push_back(
"-asan-detect-invalid-pointer-sub");
1036 if (!HwasanAbi.empty()) {
1037 CmdArgs.push_back(
"-default-function-attr");
1038 CmdArgs.push_back(Args.MakeArgString(
"hwasan-abi=" + HwasanAbi));
1041 if (Sanitizers.has(SanitizerKind::HWAddress)) {
1042 CmdArgs.push_back(
"-target-feature");
1043 CmdArgs.push_back(
"+tagged-globals");
1051 if (Sanitizers.has(SanitizerKind::Memory) ||
1052 Sanitizers.has(SanitizerKind::Address))
1053 CmdArgs.push_back(
"-fno-assume-sane-operator-new");
1057 if (Sanitizers.hasOneOf(CFIClasses) && !TC.
getTriple().isOSWindows() &&
1058 !Args.hasArg(options::OPT_fvisibility_EQ)) {
1059 TC.
getDriver().
Diag(clang::diag::err_drv_argument_only_allowed_with)
1066 TC.
getDriver().
Diag(diag::err_stack_tagging_requires_hardware_feature);
1070 bool DiagnoseErrors) {
1071 assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
1072 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
1073 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
1074 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
1075 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
1076 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) &&
1077 "Invalid argument in parseArgValues!");
1079 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1080 const char *
Value = A->getValue(i);
1083 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
1084 0 == strcmp(
"all", Value))
1091 else if (DiagnoseErrors)
1092 D.
Diag(clang::diag::err_drv_unsupported_option_argument)
1093 << A->getOption().getName() <<
Value;
1099 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
1100 A->getOption().matches(options::OPT_fno_sanitize_coverage));
1102 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1103 const char *
Value = A->getValue(i);
1104 int F = llvm::StringSwitch<int>(
Value)
1122 D.
Diag(clang::diag::err_drv_unsupported_option_argument)
1123 << A->getOption().getName() <<
Value;
1131 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
1134 const auto *Arg = *I;
1135 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
1138 if (AddKinds & Mask)
1140 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
1143 Mask &= ~RemoveKinds;
1146 llvm_unreachable(
"arg list didn't provide expected value");
1150 assert(A->getOption().matches(options::OPT_fsanitize_EQ)
1151 &&
"Invalid argument in describeSanitizerArg!");
1153 std::string Sanitizers;
1154 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1158 if (!Sanitizers.empty())
1160 Sanitizers += A->getValue(i);
1164 assert(!Sanitizers.empty() &&
"arg didn't provide expected value");
1165 return "-fsanitize=" + Sanitizers;
static const SanitizerMask NeedsUbsanRt
static const SanitizerMask RecoverableByDefault
static const SanitizerMask AlwaysRecoverable
bool isUsingLTO() const
Returns true if we are performing any kind of LTO.
static const SanitizerMask SupportsCoverage
constexpr XRayInstrMask Function
void addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, types::ID InputType) const
DiagnosticBuilder Diag(unsigned DiagID) const
static const SanitizerMask NeedsUnwindTables
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.
bool needsUbsanRt() const
static const SanitizerMask CFIClasses
SanitizerMask Mask
Bitmask of enabled sanitizers.
static const SanitizerMask NotAllowedWithMinimalRuntime
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
static const SanitizerMask NeedsUbsanCxxRt
llvm::vfs::FileSystem & getVFS() const
bool needsCfiDiagRt() const
static const SanitizerMask NeedsLTO
bool needsUnwindTables() const
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 const SanitizerMask NotAllowedWithTrap
static const SanitizerMask TrappingSupported
static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A)
Parse -f(no-)?sanitize-coverage= flag values, diagnosing any invalid components.
static void addIncludeLinkerOption(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, StringRef SymbolName)
bool CCCIsCXX() const
Whether the driver should follow g++ like behavior.
static const SanitizerMask TrappingDefault
Dataflow Directional Tag Classes.
static void addDefaultBlacklists(const Driver &D, SanitizerMask Kinds, std::vector< std::string > &BlacklistFiles)
static const SanitizerMask RequiresPIE
std::unique_ptr< DiagnosticConsumer > create(StringRef OutputFile, DiagnosticOptions *Diags, bool MergeChildRecords=false)
Returns a DiagnosticConsumer that serializes diagnostics to a bitcode file.
static const SanitizerMask CompatibleWithMinimalRuntime
SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups)
Parse a single value from a -fsanitize= or -fno-sanitize= value list.
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).
SanitizerMask expandSanitizerGroups(SanitizerMask Kinds)
For each sanitizer group bit set in Kinds, set the bits for sanitizers this group enables...
static const SanitizerMask Unrecoverable
bool Add(InterpState &S, CodePtr OpPC)
static const SanitizerMask LegacyFsanitizeRecoverMask
static SanitizerMask parseSanitizeTrapArgs(const Driver &D, const llvm::opt::ArgList &Args)
SanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args)
Parses the sanitizer arguments from an argument list.
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 bool hasTargetFeatureMTE(const llvm::opt::ArgStringList &CmdArgs)
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...
std::string ResourceDir
The path to the compiler resource directory.