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;
51 SanitizerKind::Undefined | SanitizerKind::Integer |
53 SanitizerKind::FloatDivideByZero;
55 SanitizerKind::Unreachable | SanitizerKind::Return;
57 SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress;
59 SanitizerKind::Undefined | SanitizerKind::Integer;
63 SanitizerKind::UnsignedIntegerOverflow | SanitizerKind::ImplicitConversion |
65 SanitizerKind::CFI | SanitizerKind::FloatDivideByZero;
68 SanitizerKind::CFIVCall | SanitizerKind::CFINVCall |
69 SanitizerKind::CFIMFCall | SanitizerKind::CFIDerivedCast |
70 SanitizerKind::CFIUnrelatedCast;
72 TrappingSupported | SanitizerKind::Scudo | SanitizerKind::ShadowCallStack;
106 const llvm::opt::ArgList &Args,
121 std::vector<std::string> &BlacklistFiles) {
125 } Blacklists[] = {{
"asan_blacklist.txt", SanitizerKind::Address},
126 {
"hwasan_blacklist.txt", SanitizerKind::HWAddress},
127 {
"memtag_blacklist.txt", SanitizerKind::MemTag},
128 {
"msan_blacklist.txt", SanitizerKind::Memory},
129 {
"tsan_blacklist.txt", SanitizerKind::Thread},
130 {
"dfsan_abilist.txt", SanitizerKind::DataFlow},
131 {
"cfi_blacklist.txt", SanitizerKind::CFI},
132 {
"ubsan_blacklist.txt",
133 SanitizerKind::Undefined | SanitizerKind::Integer |
135 SanitizerKind::FloatDivideByZero}};
137 for (
auto BL : Blacklists) {
138 if (!(Kinds & BL.Mask))
142 llvm::sys::path::append(Path,
"share", BL.File);
143 if (llvm::sys::fs::exists(Path))
144 BlacklistFiles.push_back(Path.str());
145 else if (BL.Mask == SanitizerKind::CFI)
148 D.
Diag(clang::diag::err_drv_no_such_file) << Path;
155 #define SANITIZER(NAME, ID) 156 #define SANITIZER_GROUP(NAME, ID, ALIAS) \ 157 if (Kinds & SanitizerKind::ID) \ 158 Kinds |= SanitizerKind::ID##Group; 159 #include "clang/Basic/Sanitizers.def" 164 const llvm::opt::ArgList &Args) {
171 for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
173 const auto *Arg = *I;
174 if (Arg->getOption().matches(options::OPT_fsanitize_trap_EQ)) {
178 if (
SanitizerMask InvalidValues = Add & ~TrappingSupportedWithGroups) {
180 S.
Mask = InvalidValues;
181 D.
Diag(diag::err_drv_unsupported_option_argument) <<
"-fsanitize-trap" 185 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) {
188 }
else if (Arg->getOption().matches(
189 options::OPT_fsanitize_undefined_trap_on_error)) {
194 }
else if (Arg->getOption().matches(
195 options::OPT_fno_sanitize_undefined_trap_on_error)) {
202 TrappingKinds |= TrappingDefault & ~TrapRemove;
204 return TrappingKinds;
209 if (needsAsanRt() || needsMsanRt() || needsHwasanRt() || needsTsanRt() ||
210 needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() ||
211 (needsScudoRt() && !requiresMinimalRuntime()))
214 return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) ||
219 return !(Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
220 CfiCrossDso && !ImplicitCfiRuntime;
224 return (Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
225 CfiCrossDso && !ImplicitCfiRuntime;
237 return static_cast<bool>(Sanitizers.Mask &
NeedsLTO);
241 const llvm::opt::ArgList &Args) {
255 CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
256 options::OPT_fno_sanitize_cfi_cross_dso,
false);
265 Args.hasFlag(options::OPT_fsanitize_minimal_runtime,
266 options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime);
269 Arg *OptLevel = Args.getLastArg(options::OPT_O_Group);
270 bool RemoveObjectSizeAtO0 =
271 !OptLevel || OptLevel->getOption().matches(options::OPT_O0);
273 for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
275 const auto *Arg = *I;
276 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
280 if (RemoveObjectSizeAtO0) {
281 AllRemove |= SanitizerKind::ObjectSize;
285 if (Add & SanitizerKind::ObjectSize)
286 D.
Diag(diag::warn_drv_object_size_disabled_O0)
287 << Arg->getAsString(Args);
298 Add & InvalidTrappingKinds & ~DiagnosedKinds) {
300 D.
Diag(diag::err_drv_argument_not_allowed_with)
301 << Desc <<
"-fsanitize-trap=undefined";
302 DiagnosedKinds |= KindsToDiagnose;
304 Add &= ~InvalidTrappingKinds;
306 if (MinimalRuntime) {
308 Add & NotAllowedWithMinimalRuntime & ~DiagnosedKinds) {
310 D.
Diag(diag::err_drv_argument_not_allowed_with)
311 << Desc <<
"-fsanitize-minimal-runtime";
312 DiagnosedKinds |= KindsToDiagnose;
314 Add &= ~NotAllowedWithMinimalRuntime;
327 if (CfiCrossDso && (Add & SanitizerKind::CFIMFCall & ~DiagnosedKinds)) {
328 D.
Diag(diag::err_drv_argument_not_allowed_with)
329 <<
"-fsanitize=cfi-mfcall" 330 <<
"-fsanitize-cfi-cross-dso";
332 DiagnosedKinds |= SanitizerKind::CFIMFCall;
335 if (
SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
337 D.
Diag(diag::err_drv_unsupported_opt_for_target)
339 DiagnosedKinds |= KindsToDiagnose;
347 if (
const llvm::opt::Arg *NoRTTIArg = TC.
getRTTIArg()) {
348 assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) &&
349 "RTTI disabled without -fno-rtti option?");
352 D.
Diag(diag::err_drv_argument_not_allowed_with)
353 <<
"-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
357 D.
Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
361 AllRemove |= SanitizerKind::Vptr;
369 Add &= ~InvalidTrappingKinds;
370 if (MinimalRuntime) {
371 Add &= ~NotAllowedWithMinimalRuntime;
377 if (Add & SanitizerKind::Fuzzer)
378 Add |= SanitizerKind::FuzzerNoLink;
381 if (Add & SanitizerKind::FuzzerNoLink) {
390 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
397 std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
398 std::make_pair(SanitizerKind::Address,
399 SanitizerKind::Thread | SanitizerKind::Memory),
400 std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory),
401 std::make_pair(SanitizerKind::Leak,
402 SanitizerKind::Thread | SanitizerKind::Memory),
403 std::make_pair(SanitizerKind::KernelAddress,
404 SanitizerKind::Address | SanitizerKind::Leak |
405 SanitizerKind::Thread | SanitizerKind::Memory),
406 std::make_pair(SanitizerKind::HWAddress,
407 SanitizerKind::Address | SanitizerKind::Thread |
408 SanitizerKind::Memory | SanitizerKind::KernelAddress),
409 std::make_pair(SanitizerKind::Scudo,
410 SanitizerKind::Address | SanitizerKind::HWAddress |
411 SanitizerKind::Leak | SanitizerKind::Thread |
412 SanitizerKind::Memory | SanitizerKind::KernelAddress),
413 std::make_pair(SanitizerKind::SafeStack,
414 SanitizerKind::Address | SanitizerKind::HWAddress |
415 SanitizerKind::Leak | SanitizerKind::Thread |
416 SanitizerKind::Memory | SanitizerKind::KernelAddress),
417 std::make_pair(SanitizerKind::KernelHWAddress,
418 SanitizerKind::Address | SanitizerKind::HWAddress |
419 SanitizerKind::Leak | SanitizerKind::Thread |
420 SanitizerKind::Memory | SanitizerKind::KernelAddress |
421 SanitizerKind::SafeStack),
422 std::make_pair(SanitizerKind::KernelMemory,
423 SanitizerKind::Address | SanitizerKind::HWAddress |
424 SanitizerKind::Leak | SanitizerKind::Thread |
425 SanitizerKind::Memory | SanitizerKind::KernelAddress |
426 SanitizerKind::Scudo | SanitizerKind::SafeStack),
427 std::make_pair(SanitizerKind::MemTag,
428 SanitizerKind::Address | SanitizerKind::KernelAddress |
429 SanitizerKind::HWAddress |
430 SanitizerKind::KernelHWAddress)};
436 for (
auto G : IncompatibleGroups) {
438 if ((Default & Group) && (Kinds & G.second))
452 D.
Diag(diag::err_drv_argument_only_allowed_with)
456 if ((Kinds & SanitizerKind::ShadowCallStack) &&
457 TC.
getTriple().getArch() == llvm::Triple::aarch64 &&
458 !llvm::AArch64::isX18ReservedByDefault(TC.
getTriple()) &&
459 !Args.hasArg(options::OPT_ffixed_x18)) {
460 D.
Diag(diag::err_drv_argument_only_allowed_with)
469 if (~Supported & SanitizerKind::Vptr) {
474 KindsToDiagnose &= ~SanitizerKind::CFI;
475 if (KindsToDiagnose) {
477 S.
Mask = KindsToDiagnose;
478 D.
Diag(diag::err_drv_unsupported_opt_for_target)
480 Kinds &= ~KindsToDiagnose;
485 for (
auto G : IncompatibleGroups) {
489 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
492 Kinds &= ~Incompatible;
505 for (
const auto *Arg : Args) {
506 const char *DeprecatedReplacement =
nullptr;
507 if (Arg->getOption().matches(options::OPT_fsanitize_recover)) {
508 DeprecatedReplacement =
509 "-fsanitize-recover=undefined,integer' or '-fsanitize-recover=all";
512 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover)) {
513 DeprecatedReplacement =
"-fno-sanitize-recover=undefined,integer' or " 514 "'-fno-sanitize-recover=all";
517 }
else if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
522 Add & Unrecoverable & ~DiagnosedUnrecoverableKinds) {
524 SetToDiagnose.
Mask |= KindsToDiagnose;
525 D.
Diag(diag::err_drv_unsupported_option_argument)
526 << Arg->getOption().getName() <<
toString(SetToDiagnose);
527 DiagnosedUnrecoverableKinds |= KindsToDiagnose;
531 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {
536 Remove & AlwaysRecoverable & ~DiagnosedAlwaysRecoverableKinds) {
538 SetToDiagnose.
Mask |= KindsToDiagnose;
539 D.
Diag(diag::err_drv_unsupported_option_argument)
540 << Arg->getOption().getName() <<
toString(SetToDiagnose);
541 DiagnosedAlwaysRecoverableKinds |= KindsToDiagnose;
546 if (DeprecatedReplacement) {
547 D.
Diag(diag::warn_drv_deprecated_arg) << Arg->getAsString(Args)
548 << DeprecatedReplacement;
551 RecoverableKinds &= Kinds;
552 RecoverableKinds &= ~Unrecoverable;
554 TrappingKinds &= Kinds;
555 RecoverableKinds &= ~TrappingKinds;
561 for (
const auto *Arg : Args) {
562 if (Arg->getOption().matches(options::OPT_fsanitize_blacklist)) {
564 std::string BLPath = Arg->getValue();
565 if (llvm::sys::fs::exists(BLPath)) {
566 BlacklistFiles.push_back(BLPath);
567 ExtraDeps.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 BlacklistFiles.clear();
580 std::unique_ptr<llvm::SpecialCaseList> SCL(
583 D.
Diag(clang::diag::err_drv_malformed_sanitizer_blacklist) << BLError;
587 if (AllAddedKinds & SanitizerKind::Memory) {
589 Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
590 options::OPT_fsanitize_memory_track_origins,
591 options::OPT_fno_sanitize_memory_track_origins)) {
592 if (A->getOption().matches(options::OPT_fsanitize_memory_track_origins)) {
593 MsanTrackOrigins = 2;
594 }
else if (A->getOption().matches(
595 options::OPT_fno_sanitize_memory_track_origins)) {
596 MsanTrackOrigins = 0;
598 StringRef S = A->getValue();
599 if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
600 MsanTrackOrigins > 2) {
601 D.
Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
606 Args.hasFlag(options::OPT_fsanitize_memory_use_after_dtor,
607 options::OPT_fno_sanitize_memory_use_after_dtor,
609 NeedPIE |= !(TC.
getTriple().isOSLinux() &&
610 TC.
getTriple().getArch() == llvm::Triple::x86_64);
612 MsanUseAfterDtor =
false;
615 if (AllAddedKinds & SanitizerKind::Thread) {
616 TsanMemoryAccess = Args.hasFlag(
617 options::OPT_fsanitize_thread_memory_access,
618 options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess);
619 TsanFuncEntryExit = Args.hasFlag(
620 options::OPT_fsanitize_thread_func_entry_exit,
621 options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit);
623 Args.hasFlag(options::OPT_fsanitize_thread_atomics,
624 options::OPT_fno_sanitize_thread_atomics, TsanAtomics);
627 if (AllAddedKinds & SanitizerKind::CFI) {
630 NeedPIE |= CfiCrossDso;
631 CfiICallGeneralizePointers =
632 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
634 if (CfiCrossDso && CfiICallGeneralizePointers)
635 D.
Diag(diag::err_drv_argument_not_allowed_with)
636 <<
"-fsanitize-cfi-cross-dso" 637 <<
"-fsanitize-cfi-icall-generalize-pointers";
640 Stats = Args.hasFlag(options::OPT_fsanitize_stats,
641 options::OPT_fno_sanitize_stats,
false);
643 if (MinimalRuntime) {
646 if (IncompatibleMask)
647 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
648 <<
"-fsanitize-minimal-runtime" 651 SanitizerMask NonTrappingCfi = Kinds & SanitizerKind::CFI & ~TrappingKinds;
653 D.
Diag(clang::diag::err_drv_argument_only_allowed_with)
654 <<
"fsanitize-minimal-runtime" 655 <<
"fsanitize-trap=cfi";
660 for (
const auto *Arg : Args) {
661 if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
662 int LegacySanitizeCoverage;
663 if (Arg->getNumValues() == 1 &&
664 !StringRef(Arg->getValue(0))
665 .getAsInteger(0, LegacySanitizeCoverage)) {
666 CoverageFeatures = 0;
668 if (LegacySanitizeCoverage != 0) {
669 D.
Diag(diag::warn_drv_deprecated_arg)
670 << Arg->getAsString(Args) <<
"-fsanitize-coverage=trace-pc-guard";
678 if (!(AllAddedKinds & ~AllRemove & ~
setGroupBits(SupportsCoverage))) {
681 CoverageFeatures = 0;
683 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
690 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
691 <<
"-fsanitize-coverage=func" 692 <<
"-fsanitize-coverage=bb";
693 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures &
CoverageEdge))
694 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
695 <<
"-fsanitize-coverage=func" 696 <<
"-fsanitize-coverage=edge";
697 if ((CoverageFeatures & CoverageBB) && (CoverageFeatures & CoverageEdge))
698 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
699 <<
"-fsanitize-coverage=bb" 700 <<
"-fsanitize-coverage=edge";
704 D.
Diag(clang::diag::warn_drv_deprecated_arg)
705 <<
"-fsanitize-coverage=trace-bb" 706 <<
"-fsanitize-coverage=trace-pc-guard";
708 D.
Diag(clang::diag::warn_drv_deprecated_arg)
709 <<
"-fsanitize-coverage=8bit-counters" 710 <<
"-fsanitize-coverage=trace-pc-guard";
712 int InsertionPointTypes = CoverageFunc | CoverageBB |
CoverageEdge;
713 int InstrumentationTypes =
715 if ((CoverageFeatures & InsertionPointTypes) &&
716 !(CoverageFeatures & InstrumentationTypes)) {
717 D.
Diag(clang::diag::warn_drv_deprecated_arg)
718 <<
"-fsanitize-coverage=[func|bb|edge]" 719 <<
"-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc]";
723 if (!(CoverageFeatures & InsertionPointTypes)) {
724 if (CoverageFeatures &
733 Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan,
737 ImplicitCfiRuntime = TC.
getTriple().isAndroid();
739 if (AllAddedKinds & SanitizerKind::Address) {
742 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
743 StringRef S = A->getValue();
745 if (S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
746 AsanFieldPadding > 2) {
747 D.
Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
751 if (Arg *WindowsDebugRTArg =
752 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
753 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
754 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
755 switch (WindowsDebugRTArg->getOption().getID()) {
756 case options::OPT__SLASH_MTd:
757 case options::OPT__SLASH_MDd:
758 case options::OPT__SLASH_LDd:
759 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
760 << WindowsDebugRTArg->getAsString(Args)
762 D.
Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
766 AsanUseAfterScope = Args.hasFlag(
767 options::OPT_fsanitize_address_use_after_scope,
768 options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);
770 AsanPoisonCustomArrayCookie = Args.hasFlag(
771 options::OPT_fsanitize_address_poison_custom_array_cookie,
772 options::OPT_fno_sanitize_address_poison_custom_array_cookie,
773 AsanPoisonCustomArrayCookie);
778 AsanGlobalsDeadStripping =
781 Args.hasArg(options::OPT_fsanitize_address_globals_dead_stripping);
783 AsanUseOdrIndicator =
784 Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
785 options::OPT_fno_sanitize_address_use_odr_indicator,
786 AsanUseOdrIndicator);
788 if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) {
789 AsanInvalidPointerCmp =
true;
792 if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) {
793 AsanInvalidPointerSub =
true;
797 AsanUseAfterScope =
false;
800 SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract;
801 if (AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) {
802 TC.
getDriver().
Diag(clang::diag::err_drv_argument_only_allowed_with)
804 SanitizerKind::PointerCompare |
805 SanitizerKind::PointerSubtract)
806 <<
"-fsanitize=address";
810 if (AllAddedKinds & SanitizerKind::HWAddress) {
811 if (Arg *HwasanAbiArg =
812 Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {
813 HwasanAbi = HwasanAbiArg->getValue();
814 if (HwasanAbi !=
"platform" && HwasanAbi !=
"interceptor")
815 D.
Diag(clang::diag::err_drv_invalid_value)
816 << HwasanAbiArg->getAsString(Args) << HwasanAbi;
818 HwasanAbi =
"interceptor";
822 if (AllAddedKinds & SanitizerKind::SafeStack) {
824 SafeStackRuntime = !TC.
getTriple().isOSFuchsia();
829 Args.hasArg(options::OPT_fsanitize_link_cxx_runtime) || D.
CCCIsCXX();
832 Sanitizers.Mask |= Kinds;
833 RecoverableSanitizers.Mask |= RecoverableKinds;
834 TrapSanitizers.Mask |= TrappingKinds;
835 assert(!(RecoverableKinds & TrappingKinds) &&
836 "Overlap between recoverable and trapping sanitizers");
841 #define SANITIZER(NAME, ID) \ 842 if (Sanitizers.has(SanitizerKind::ID)) { \ 847 #include "clang/Basic/Sanitizers.def" 852 const llvm::opt::ArgList &Args,
853 llvm::opt::ArgStringList &CmdArgs,
854 StringRef SymbolName) {
856 LinkerOptionFlag =
"--linker-option=/include:";
857 if (TC.
getTriple().getArch() == llvm::Triple::x86) {
859 LinkerOptionFlag +=
'_';
861 LinkerOptionFlag += SymbolName;
862 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
866 llvm::opt::ArgStringList &CmdArgs,
877 std::pair<int, const char *> CoverageFlags[] = {
878 std::make_pair(
CoverageFunc,
"-fsanitize-coverage-type=1"),
879 std::make_pair(
CoverageBB,
"-fsanitize-coverage-type=2"),
880 std::make_pair(
CoverageEdge,
"-fsanitize-coverage-type=3"),
893 for (
auto F : CoverageFlags) {
894 if (CoverageFeatures & F.first)
895 CmdArgs.push_back(F.second);
898 if (TC.
getTriple().isOSWindows() && needsUbsanRt()) {
901 CmdArgs.push_back(Args.MakeArgString(
902 "--dependent-lib=" + TC.
getCompilerRT(Args,
"ubsan_standalone")));
904 CmdArgs.push_back(Args.MakeArgString(
905 "--dependent-lib=" + TC.
getCompilerRT(Args,
"ubsan_standalone_cxx")));
907 if (TC.
getTriple().isOSWindows() && needsStatsRt()) {
908 CmdArgs.push_back(Args.MakeArgString(
"--dependent-lib=" +
915 CmdArgs.push_back(Args.MakeArgString(
"--dependent-lib=" +
920 if (Sanitizers.empty())
922 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize=" +
toString(Sanitizers)));
924 if (!RecoverableSanitizers.empty())
925 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-recover=" +
928 if (!TrapSanitizers.empty())
930 Args.MakeArgString(
"-fsanitize-trap=" +
toString(TrapSanitizers)));
932 for (
const auto &BLPath : BlacklistFiles) {
934 BlacklistOpt += BLPath;
935 CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
937 for (
const auto &Dep : ExtraDeps) {
940 CmdArgs.push_back(Args.MakeArgString(ExtraDepOpt));
943 if (MsanTrackOrigins)
944 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-memory-track-origins=" +
945 Twine(MsanTrackOrigins)));
947 if (MsanUseAfterDtor)
948 CmdArgs.push_back(
"-fsanitize-memory-use-after-dtor");
951 if (!TsanMemoryAccess) {
952 CmdArgs.push_back(
"-mllvm");
953 CmdArgs.push_back(
"-tsan-instrument-memory-accesses=0");
954 CmdArgs.push_back(
"-mllvm");
955 CmdArgs.push_back(
"-tsan-instrument-memintrinsics=0");
957 if (!TsanFuncEntryExit) {
958 CmdArgs.push_back(
"-mllvm");
959 CmdArgs.push_back(
"-tsan-instrument-func-entry-exit=0");
962 CmdArgs.push_back(
"-mllvm");
963 CmdArgs.push_back(
"-tsan-instrument-atomics=0");
967 CmdArgs.push_back(
"-fsanitize-cfi-cross-dso");
969 if (CfiICallGeneralizePointers)
970 CmdArgs.push_back(
"-fsanitize-cfi-icall-generalize-pointers");
973 CmdArgs.push_back(
"-fsanitize-stats");
976 CmdArgs.push_back(
"-fsanitize-minimal-runtime");
978 if (AsanFieldPadding)
979 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-address-field-padding=" +
980 Twine(AsanFieldPadding)));
982 if (AsanUseAfterScope)
983 CmdArgs.push_back(
"-fsanitize-address-use-after-scope");
985 if (AsanPoisonCustomArrayCookie)
986 CmdArgs.push_back(
"-fsanitize-address-poison-custom-array-cookie");
988 if (AsanGlobalsDeadStripping)
989 CmdArgs.push_back(
"-fsanitize-address-globals-dead-stripping");
991 if (AsanUseOdrIndicator)
992 CmdArgs.push_back(
"-fsanitize-address-use-odr-indicator");
994 if (AsanInvalidPointerCmp) {
995 CmdArgs.push_back(
"-mllvm");
996 CmdArgs.push_back(
"-asan-detect-invalid-pointer-cmp");
999 if (AsanInvalidPointerSub) {
1000 CmdArgs.push_back(
"-mllvm");
1001 CmdArgs.push_back(
"-asan-detect-invalid-pointer-sub");
1004 if (!HwasanAbi.empty()) {
1005 CmdArgs.push_back(
"-default-function-attr");
1006 CmdArgs.push_back(Args.MakeArgString(
"hwasan-abi=" + HwasanAbi));
1014 if (Sanitizers.has(SanitizerKind::Memory) ||
1015 Sanitizers.has(SanitizerKind::Address))
1016 CmdArgs.push_back(
"-fno-assume-sane-operator-new");
1020 if (Sanitizers.hasOneOf(CFIClasses) && !TC.
getTriple().isOSWindows() &&
1021 !Args.hasArg(options::OPT_fvisibility_EQ)) {
1022 TC.
getDriver().
Diag(clang::diag::err_drv_argument_only_allowed_with)
1030 bool DiagnoseErrors) {
1031 assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
1032 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
1033 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
1034 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
1035 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
1036 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) &&
1037 "Invalid argument in parseArgValues!");
1039 for (
int i = 0, n = A->getNumValues();
i != n; ++
i) {
1040 const char *
Value = A->getValue(
i);
1043 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
1044 0 == strcmp(
"all", Value))
1051 else if (DiagnoseErrors)
1052 D.
Diag(clang::diag::err_drv_unsupported_option_argument)
1053 << A->getOption().getName() <<
Value;
1059 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
1060 A->getOption().matches(options::OPT_fno_sanitize_coverage));
1062 for (
int i = 0, n = A->getNumValues();
i != n; ++
i) {
1063 const char *
Value = A->getValue(
i);
1064 int F = llvm::StringSwitch<int>(
Value)
1082 D.
Diag(clang::diag::err_drv_unsupported_option_argument)
1083 << A->getOption().getName() <<
Value;
1091 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
1094 const auto *Arg = *I;
1095 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
1098 if (AddKinds & Mask)
1100 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
1103 Mask &= ~RemoveKinds;
1106 llvm_unreachable(
"arg list didn't provide expected value");
1110 assert(A->getOption().matches(options::OPT_fsanitize_EQ)
1111 &&
"Invalid argument in describeSanitizerArg!");
1113 std::string Sanitizers;
1114 for (
int i = 0, n = A->getNumValues();
i != n; ++
i) {
1118 if (!Sanitizers.empty())
1120 Sanitizers += A->getValue(
i);
1124 assert(!Sanitizers.empty() &&
"arg didn't provide expected value");
1125 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
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
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 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.