15#include "llvm/ADT/StringExtras.h"
16#include "llvm/ADT/StringRef.h"
17#include "llvm/ADT/StringSwitch.h"
18#include "llvm/Support/Path.h"
19#include "llvm/Support/SpecialCaseList.h"
20#include "llvm/Support/VirtualFileSystem.h"
21#include "llvm/TargetParser/AArch64TargetParser.h"
22#include "llvm/TargetParser/RISCVTargetParser.h"
23#include "llvm/TargetParser/TargetParser.h"
24#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
32 SanitizerKind::Undefined | SanitizerKind::Integer |
33 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
34 SanitizerKind::CFI | SanitizerKind::FloatDivideByZero |
35 SanitizerKind::ObjCCast;
37 SanitizerKind::Vptr | SanitizerKind::CFI;
41 SanitizerKind::DataFlow | SanitizerKind::Scudo;
43 SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Thread |
44 SanitizerKind::Memory | SanitizerKind::DataFlow;
46 SanitizerKind::Address | SanitizerKind::HWAddress |
47 SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |
48 SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap |
49 SanitizerKind::MemtagGlobals | SanitizerKind::Memory |
50 SanitizerKind::KernelMemory | SanitizerKind::Leak |
51 SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::Bounds |
52 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
53 SanitizerKind::DataFlow | SanitizerKind::Fuzzer |
54 SanitizerKind::FuzzerNoLink | SanitizerKind::FloatDivideByZero |
55 SanitizerKind::SafeStack | SanitizerKind::ShadowCallStack |
56 SanitizerKind::Thread | SanitizerKind::ObjCCast | SanitizerKind::KCFI;
58 SanitizerKind::Undefined | SanitizerKind::Integer |
59 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
60 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;
62 SanitizerKind::Unreachable | SanitizerKind::Return;
64 SanitizerKind::KernelHWAddress |
68 (SanitizerKind::Undefined &
~SanitizerKind::Vptr) | SanitizerKind::Integer |
69 SanitizerKind::Nullability | SanitizerKind::LocalBounds |
70 SanitizerKind::CFI | SanitizerKind::FloatDivideByZero |
71 SanitizerKind::ObjCCast;
74 SanitizerKind::CFIVCall | SanitizerKind::CFINVCall |
75 SanitizerKind::CFIMFCall | SanitizerKind::CFIDerivedCast |
76 SanitizerKind::CFIUnrelatedCast;
79 SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap |
80 SanitizerKind::MemtagGlobals;
113 bool DiagnoseErrors);
118 bool DiagnoseErrors);
123 bool DiagnoseErrors);
130 const llvm::opt::ArgList &Args,
145 std::vector<std::string> &SCLFiles,
146 unsigned MalformedSCLErrorDiagID,
147 bool DiagnoseErrors) {
148 if (SCLFiles.empty())
152 std::unique_ptr<llvm::SpecialCaseList> SCL(
153 llvm::SpecialCaseList::create(SCLFiles, D.
getVFS(), BLError));
154 if (!SCL.get() && DiagnoseErrors)
155 D.
Diag(MalformedSCLErrorDiagID) << BLError;
159 std::vector<std::string> &IgnorelistFiles,
160 bool DiagnoseErrors) {
164 } Ignorelists[] = {{
"asan_ignorelist.txt", SanitizerKind::Address},
165 {
"hwasan_ignorelist.txt", SanitizerKind::HWAddress},
166 {
"memtag_ignorelist.txt", SanitizerKind::MemTag},
167 {
"msan_ignorelist.txt", SanitizerKind::Memory},
168 {
"tsan_ignorelist.txt", SanitizerKind::Thread},
169 {
"dfsan_abilist.txt", SanitizerKind::DataFlow},
170 {
"cfi_ignorelist.txt", SanitizerKind::CFI},
171 {
"ubsan_ignorelist.txt",
172 SanitizerKind::Undefined | SanitizerKind::Integer |
173 SanitizerKind::Nullability |
174 SanitizerKind::FloatDivideByZero}};
176 for (
auto BL : Ignorelists) {
177 if (!(Kinds & BL.Mask))
181 llvm::sys::path::append(Path,
"share", BL.File);
182 if (D.
getVFS().exists(Path))
183 IgnorelistFiles.push_back(std::string(Path.str()));
184 else if (BL.Mask == SanitizerKind::CFI && DiagnoseErrors)
187 D.
Diag(clang::diag::err_drv_missing_sanitizer_ignorelist) << Path;
190 D, IgnorelistFiles, clang::diag::err_drv_malformed_sanitizer_ignorelist,
197 const llvm::opt::ArgList &Args,
198 std::vector<std::string> &SCLFiles,
199 llvm::opt::OptSpecifier SCLOptionID,
200 llvm::opt::OptSpecifier NoSCLOptionID,
201 unsigned MalformedSCLErrorDiagID,
202 bool DiagnoseErrors) {
203 for (
const auto *Arg : Args) {
205 if (Arg->getOption().matches(SCLOptionID)) {
207 std::string SCLPath = Arg->getValue();
208 if (D.
getVFS().exists(SCLPath)) {
209 SCLFiles.push_back(SCLPath);
210 }
else if (DiagnoseErrors) {
211 D.
Diag(clang::diag::err_drv_no_such_file) << SCLPath;
214 }
else if (Arg->getOption().matches(NoSCLOptionID)) {
226#define SANITIZER(NAME, ID)
227#define SANITIZER_GROUP(NAME, ID, ALIAS) \
228 if (Kinds & SanitizerKind::ID) \
229 Kinds |= SanitizerKind::ID##Group;
230#include "clang/Basic/Sanitizers.def"
235 const llvm::opt::ArgList &Args,
236 bool DiagnoseErrors) {
243 for (
const llvm::opt::Arg *Arg : llvm::reverse(Args)) {
244 if (Arg->getOption().matches(options::OPT_fsanitize_trap_EQ)) {
248 SanitizerMask InvalidValues = Add & ~TrappingSupportedWithGroups;
249 if (InvalidValues && DiagnoseErrors) {
251 S.Mask = InvalidValues;
252 D.
Diag(diag::err_drv_unsupported_option_argument)
253 << Arg->getSpelling() <<
toString(S);
256 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) {
266 return TrappingKinds;
285 return !(Sanitizers.
Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
286 CfiCrossDso && !ImplicitCfiRuntime;
290 return (Sanitizers.
Mask & SanitizerKind::CFI & ~TrapSanitizers.
Mask) &&
291 CfiCrossDso && !ImplicitCfiRuntime;
307 const llvm::opt::ArgList &Args,
308 bool DiagnoseErrors) {
322 CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
323 options::OPT_fno_sanitize_cfi_cross_dso,
false);
332 Args.hasFlag(options::OPT_fsanitize_minimal_runtime,
333 options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime);
336 Arg *OptLevel = Args.getLastArg(options::OPT_O_Group);
337 bool RemoveObjectSizeAtO0 =
338 !OptLevel || OptLevel->getOption().matches(options::OPT_O0);
340 for (
const llvm::opt::Arg *Arg : llvm::reverse(Args)) {
341 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
345 if (RemoveObjectSizeAtO0) {
346 AllRemove |= SanitizerKind::ObjectSize;
350 if ((Add & SanitizerKind::ObjectSize) && DiagnoseErrors)
351 D.
Diag(diag::warn_drv_object_size_disabled_O0)
352 << Arg->getAsString(Args);
363 Add & InvalidTrappingKinds & ~DiagnosedKinds) {
364 if (DiagnoseErrors) {
366 D.
Diag(diag::err_drv_argument_not_allowed_with)
367 << Desc <<
"-fsanitize-trap=undefined";
369 DiagnosedKinds |= KindsToDiagnose;
371 Add &= ~InvalidTrappingKinds;
373 if (MinimalRuntime) {
376 if (DiagnoseErrors) {
378 D.
Diag(diag::err_drv_argument_not_allowed_with)
379 << Desc <<
"-fsanitize-minimal-runtime";
381 DiagnosedKinds |= KindsToDiagnose;
383 Add &= ~NotAllowedWithMinimalRuntime;
386 if (llvm::opt::Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
387 StringRef CM = A->getValue();
389 (Add & SanitizerKind::Function & ~DiagnosedKinds)) {
391 D.
Diag(diag::err_drv_argument_only_allowed_with)
392 <<
"-fsanitize=function"
395 DiagnosedKinds |= SanitizerKind::Function;
409 if (CfiCrossDso && (Add & SanitizerKind::CFIMFCall & ~DiagnosedKinds)) {
411 D.
Diag(diag::err_drv_argument_not_allowed_with)
412 <<
"-fsanitize=cfi-mfcall"
413 <<
"-fsanitize-cfi-cross-dso";
415 DiagnosedKinds |= SanitizerKind::CFIMFCall;
418 if (
SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
419 if (DiagnoseErrors) {
421 D.
Diag(diag::err_drv_unsupported_opt_for_target)
424 DiagnosedKinds |= KindsToDiagnose;
432 if (
const llvm::opt::Arg *NoRTTIArg = TC.
getRTTIArg()) {
433 assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) &&
434 "RTTI disabled without -fno-rtti option?");
438 D.
Diag(diag::err_drv_argument_not_allowed_with)
439 <<
"-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
444 D.
Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
448 AllRemove |= SanitizerKind::Vptr;
456 Add &= ~InvalidTrappingKinds;
457 if (MinimalRuntime) {
458 Add &= ~NotAllowedWithMinimalRuntime;
464 if (Add & SanitizerKind::Fuzzer)
465 Add |= SanitizerKind::FuzzerNoLink;
468 if (Add & SanitizerKind::FuzzerNoLink) {
477 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
484 std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
485 std::make_pair(SanitizerKind::Address,
486 SanitizerKind::Thread | SanitizerKind::Memory),
487 std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory),
488 std::make_pair(SanitizerKind::Leak,
489 SanitizerKind::Thread | SanitizerKind::Memory),
490 std::make_pair(SanitizerKind::KernelAddress,
491 SanitizerKind::Address | SanitizerKind::Leak |
492 SanitizerKind::Thread | SanitizerKind::Memory),
493 std::make_pair(SanitizerKind::HWAddress,
494 SanitizerKind::Address | SanitizerKind::Thread |
495 SanitizerKind::Memory | SanitizerKind::KernelAddress),
496 std::make_pair(SanitizerKind::Scudo,
497 SanitizerKind::Address | SanitizerKind::HWAddress |
498 SanitizerKind::Leak | SanitizerKind::Thread |
499 SanitizerKind::Memory | SanitizerKind::KernelAddress),
500 std::make_pair(SanitizerKind::SafeStack,
502 : SanitizerKind::Leak) |
503 SanitizerKind::Address | SanitizerKind::HWAddress |
504 SanitizerKind::Thread | SanitizerKind::Memory |
505 SanitizerKind::KernelAddress),
506 std::make_pair(SanitizerKind::KernelHWAddress,
507 SanitizerKind::Address | SanitizerKind::HWAddress |
508 SanitizerKind::Leak | SanitizerKind::Thread |
509 SanitizerKind::Memory | SanitizerKind::KernelAddress |
510 SanitizerKind::SafeStack),
511 std::make_pair(SanitizerKind::KernelMemory,
512 SanitizerKind::Address | SanitizerKind::HWAddress |
513 SanitizerKind::Leak | SanitizerKind::Thread |
514 SanitizerKind::Memory | SanitizerKind::KernelAddress |
515 SanitizerKind::Scudo | SanitizerKind::SafeStack),
516 std::make_pair(SanitizerKind::MemTag,
517 SanitizerKind::Address | SanitizerKind::KernelAddress |
518 SanitizerKind::HWAddress |
519 SanitizerKind::KernelHWAddress),
520 std::make_pair(SanitizerKind::KCFI, SanitizerKind::Function)};
526 for (
auto G : IncompatibleGroups) {
528 if ((
Default & Group) && (Kinds & G.second))
542 D.
Diag(diag::err_drv_argument_only_allowed_with)
546 if ((Kinds & SanitizerKind::ShadowCallStack) && TC.
getTriple().isAArch64() &&
547 !llvm::AArch64::isX18ReservedByDefault(TC.
getTriple()) &&
548 !Args.hasArg(options::OPT_ffixed_x18) && DiagnoseErrors) {
549 D.
Diag(diag::err_drv_argument_only_allowed_with)
558 if (~Supported & SanitizerKind::Vptr) {
564 if (KindsToDiagnose) {
566 S.Mask = KindsToDiagnose;
568 D.
Diag(diag::err_drv_unsupported_opt_for_target)
570 Kinds &= ~KindsToDiagnose;
575 for (
auto G : IncompatibleGroups) {
580 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
583 Kinds &= ~Incompatible;
596 for (
const auto *Arg : Args) {
597 if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
604 SetToDiagnose.
Mask |= KindsToDiagnose;
606 D.
Diag(diag::err_drv_unsupported_option_argument)
607 << Arg->getSpelling() <<
toString(SetToDiagnose);
608 DiagnosedUnrecoverableKinds |= KindsToDiagnose;
612 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {
619 SetToDiagnose.
Mask |= KindsToDiagnose;
621 D.
Diag(diag::err_drv_unsupported_option_argument)
622 << Arg->getSpelling() <<
toString(SetToDiagnose);
623 DiagnosedAlwaysRecoverableKinds |= KindsToDiagnose;
625 RecoverableKinds &= ~expandSanitizerGroups(Remove);
629 RecoverableKinds &= Kinds;
630 RecoverableKinds &= ~Unrecoverable;
632 TrappingKinds &= Kinds;
633 RecoverableKinds &= ~TrappingKinds;
638 if (!Args.hasArgNoClaim(options::OPT_fno_sanitize_ignorelist))
644 D, Args, UserIgnorelistFiles, options::OPT_fsanitize_ignorelist_EQ,
645 options::OPT_fno_sanitize_ignorelist,
646 clang::diag::err_drv_malformed_sanitizer_ignorelist, DiagnoseErrors);
649 if (AllAddedKinds & SanitizerKind::Memory) {
651 Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
652 options::OPT_fno_sanitize_memory_track_origins)) {
653 if (!A->getOption().matches(
654 options::OPT_fno_sanitize_memory_track_origins)) {
655 StringRef S = A->getValue();
656 if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
657 MsanTrackOrigins > 2) {
659 D.
Diag(clang::diag::err_drv_invalid_value)
660 << A->getAsString(Args) << S;
664 MsanUseAfterDtor = Args.hasFlag(
665 options::OPT_fsanitize_memory_use_after_dtor,
666 options::OPT_fno_sanitize_memory_use_after_dtor, MsanUseAfterDtor);
667 MsanParamRetval = Args.hasFlag(
668 options::OPT_fsanitize_memory_param_retval,
669 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
670 NeedPIE |= !(TC.
getTriple().isOSLinux() &&
671 TC.
getTriple().getArch() == llvm::Triple::x86_64);
672 }
else if (AllAddedKinds & SanitizerKind::KernelMemory) {
673 MsanUseAfterDtor =
false;
674 MsanParamRetval = Args.hasFlag(
675 options::OPT_fsanitize_memory_param_retval,
676 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
678 MsanUseAfterDtor =
false;
679 MsanParamRetval =
false;
682 if (AllAddedKinds & SanitizerKind::MemTag) {
684 Args.getLastArgValue(options::OPT_fsanitize_memtag_mode_EQ,
"sync");
685 if (S ==
"async" || S ==
"sync") {
686 MemtagMode = S.str();
688 D.
Diag(clang::diag::err_drv_invalid_value_with_suggestion)
689 <<
"-fsanitize-memtag-mode=" << S <<
"{async, sync}";
694 if (AllAddedKinds & SanitizerKind::Thread) {
695 TsanMemoryAccess = Args.hasFlag(
696 options::OPT_fsanitize_thread_memory_access,
697 options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess);
698 TsanFuncEntryExit = Args.hasFlag(
699 options::OPT_fsanitize_thread_func_entry_exit,
700 options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit);
702 Args.hasFlag(options::OPT_fsanitize_thread_atomics,
703 options::OPT_fno_sanitize_thread_atomics, TsanAtomics);
706 if (AllAddedKinds & SanitizerKind::CFI) {
709 NeedPIE |= CfiCrossDso;
710 CfiICallGeneralizePointers =
711 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
713 CfiICallNormalizeIntegers =
714 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
716 if (CfiCrossDso && CfiICallGeneralizePointers && DiagnoseErrors)
717 D.
Diag(diag::err_drv_argument_not_allowed_with)
718 <<
"-fsanitize-cfi-cross-dso"
719 <<
"-fsanitize-cfi-icall-generalize-pointers";
721 CfiCanonicalJumpTables =
722 Args.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables,
723 options::OPT_fno_sanitize_cfi_canonical_jump_tables,
true);
726 if (AllAddedKinds & SanitizerKind::KCFI) {
727 CfiICallNormalizeIntegers =
728 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
730 if (AllAddedKinds & SanitizerKind::CFI && DiagnoseErrors)
731 D.
Diag(diag::err_drv_argument_not_allowed_with)
736 Stats = Args.hasFlag(options::OPT_fsanitize_stats,
737 options::OPT_fno_sanitize_stats,
false);
739 if (MinimalRuntime) {
742 if (IncompatibleMask && DiagnoseErrors)
743 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
744 <<
"-fsanitize-minimal-runtime"
747 SanitizerMask NonTrappingCfi = Kinds & SanitizerKind::CFI & ~TrappingKinds;
748 if (NonTrappingCfi && DiagnoseErrors)
749 D.
Diag(clang::diag::err_drv_argument_only_allowed_with)
750 <<
"fsanitize-minimal-runtime"
751 <<
"fsanitize-trap=cfi";
756 for (
const auto *Arg : Args) {
757 if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
758 int LegacySanitizeCoverage;
759 if (Arg->getNumValues() == 1 &&
760 !StringRef(Arg->getValue(0))
761 .getAsInteger(0, LegacySanitizeCoverage)) {
762 CoverageFeatures = 0;
764 if (LegacySanitizeCoverage != 0 && DiagnoseErrors) {
765 D.
Diag(diag::warn_drv_deprecated_arg)
766 << Arg->getAsString(Args) <<
"-fsanitize-coverage=trace-pc-guard";
777 CoverageFeatures = 0;
779 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
781 CoverageFeatures &= ~parseCoverageFeatures(D, Arg, DiagnoseErrors);
785 if (DiagnoseErrors) {
787 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
788 <<
"-fsanitize-coverage=func"
789 <<
"-fsanitize-coverage=bb";
791 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
792 <<
"-fsanitize-coverage=func"
793 <<
"-fsanitize-coverage=edge";
795 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
796 <<
"-fsanitize-coverage=bb"
797 <<
"-fsanitize-coverage=edge";
801 D.
Diag(clang::diag::warn_drv_deprecated_arg)
802 <<
"-fsanitize-coverage=trace-bb"
803 <<
"-fsanitize-coverage=trace-pc-guard";
805 D.
Diag(clang::diag::warn_drv_deprecated_arg)
806 <<
"-fsanitize-coverage=8bit-counters"
807 <<
"-fsanitize-coverage=trace-pc-guard";
815 if ((CoverageFeatures & InsertionPointTypes) &&
816 !(CoverageFeatures & InstrumentationTypes) && DiagnoseErrors) {
817 D.
Diag(clang::diag::warn_drv_deprecated_arg)
818 <<
"-fsanitize-coverage=[func|bb|edge]"
819 <<
"-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc],["
824 if (!(CoverageFeatures & InsertionPointTypes)) {
825 if (CoverageFeatures &
838 if (CoverageFeatures) {
840 D, Args, CoverageAllowlistFiles,
841 options::OPT_fsanitize_coverage_allowlist, OptSpecifier(),
842 clang::diag::err_drv_malformed_sanitizer_coverage_allowlist,
845 D, Args, CoverageIgnorelistFiles,
846 options::OPT_fsanitize_coverage_ignorelist, OptSpecifier(),
847 clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist,
852 for (
const auto *Arg :
853 Args.filtered(options::OPT_fexperimental_sanitize_metadata_EQ,
854 options::OPT_fno_experimental_sanitize_metadata_EQ)) {
855 if (Arg->getOption().matches(
856 options::OPT_fexperimental_sanitize_metadata_EQ)) {
858 BinaryMetadataFeatures |=
862 BinaryMetadataFeatures &=
863 ~parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);
868 if (BinaryMetadataFeatures) {
870 D, Args, BinaryMetadataIgnorelistFiles,
871 options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ,
873 clang::diag::err_drv_malformed_sanitizer_metadata_ignorelist,
878 Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan,
882 ImplicitCfiRuntime = TC.
getTriple().isAndroid();
884 if (AllAddedKinds & SanitizerKind::Address) {
887 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
888 StringRef S = A->getValue();
890 if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
891 AsanFieldPadding > 2) &&
893 D.
Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
897 if (Arg *WindowsDebugRTArg =
898 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
899 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
900 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
901 switch (WindowsDebugRTArg->getOption().getID()) {
902 case options::OPT__SLASH_MTd:
903 case options::OPT__SLASH_MDd:
904 case options::OPT__SLASH_LDd:
905 if (DiagnoseErrors) {
906 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
907 << WindowsDebugRTArg->getAsString(Args)
909 D.
Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
914 StableABI = Args.hasFlag(options::OPT_fsanitize_stable_abi,
915 options::OPT_fno_sanitize_stable_abi,
false);
917 AsanUseAfterScope = Args.hasFlag(
918 options::OPT_fsanitize_address_use_after_scope,
919 options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);
921 AsanPoisonCustomArrayCookie = Args.hasFlag(
922 options::OPT_fsanitize_address_poison_custom_array_cookie,
923 options::OPT_fno_sanitize_address_poison_custom_array_cookie,
924 AsanPoisonCustomArrayCookie);
926 AsanOutlineInstrumentation =
927 Args.hasFlag(options::OPT_fsanitize_address_outline_instrumentation,
928 options::OPT_fno_sanitize_address_outline_instrumentation,
929 AsanOutlineInstrumentation);
934 AsanGlobalsDeadStripping = Args.hasFlag(
935 options::OPT_fsanitize_address_globals_dead_stripping,
936 options::OPT_fno_sanitize_address_globals_dead_stripping,
944 AsanUseOdrIndicator =
945 Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
946 options::OPT_fno_sanitize_address_use_odr_indicator,
949 if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) {
950 AsanInvalidPointerCmp =
true;
953 if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) {
954 AsanInvalidPointerSub =
true;
958 (Args.hasArg(options::OPT_mkernel) ||
959 Args.hasArg(options::OPT_fapple_kext))) {
960 AsanDtorKind = llvm::AsanDtorKind::None;
963 if (
const auto *Arg =
964 Args.getLastArg(options::OPT_sanitize_address_destructor_EQ)) {
966 if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid && DiagnoseErrors) {
967 TC.
getDriver().
Diag(clang::diag::err_drv_unsupported_option_argument)
968 << Arg->getSpelling() << Arg->getValue();
970 AsanDtorKind = parsedAsanDtorKind;
973 if (
const auto *Arg = Args.getLastArg(
974 options::OPT_sanitize_address_use_after_return_EQ)) {
975 auto parsedAsanUseAfterReturn =
977 if (parsedAsanUseAfterReturn ==
978 llvm::AsanDetectStackUseAfterReturnMode::Invalid &&
980 TC.
getDriver().
Diag(clang::diag::err_drv_unsupported_option_argument)
981 << Arg->getSpelling() << Arg->getValue();
983 AsanUseAfterReturn = parsedAsanUseAfterReturn;
987 AsanUseAfterScope =
false;
990 SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract;
991 if ((AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) &&
993 TC.
getDriver().
Diag(clang::diag::err_drv_argument_only_allowed_with)
995 SanitizerKind::PointerCompare |
996 SanitizerKind::PointerSubtract)
997 <<
"-fsanitize=address";
1001 if (AllAddedKinds & SanitizerKind::HWAddress) {
1002 if (Arg *HwasanAbiArg =
1003 Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {
1004 HwasanAbi = HwasanAbiArg->getValue();
1005 if (HwasanAbi !=
"platform" && HwasanAbi !=
"interceptor" &&
1007 D.
Diag(clang::diag::err_drv_invalid_value)
1008 << HwasanAbiArg->getAsString(Args) << HwasanAbi;
1010 HwasanAbi =
"interceptor";
1012 if (TC.
getTriple().getArch() == llvm::Triple::x86_64)
1013 HwasanUseAliases = Args.hasFlag(
1014 options::OPT_fsanitize_hwaddress_experimental_aliasing,
1015 options::OPT_fno_sanitize_hwaddress_experimental_aliasing,
1019 if (AllAddedKinds & SanitizerKind::SafeStack) {
1026 Args.hasFlag(options::OPT_fsanitize_link_runtime,
1027 options::OPT_fno_sanitize_link_runtime, LinkRuntimes);
1030 LinkCXXRuntimes = Args.hasArg(options::OPT_fsanitize_link_cxx_runtime,
1031 options::OPT_fno_sanitize_link_cxx_runtime,
1035 NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile,
1036 options::OPT_fmemory_profile_EQ,
1037 options::OPT_fno_memory_profile,
false);
1040 Sanitizers.
Mask |= Kinds;
1041 RecoverableSanitizers.
Mask |= RecoverableKinds;
1042 TrapSanitizers.
Mask |= TrappingKinds;
1043 assert(!(RecoverableKinds & TrappingKinds) &&
1044 "Overlap between recoverable and trapping sanitizers");
1049#define SANITIZER(NAME, ID) \
1050 if (Sanitizers.has(SanitizerKind::ID)) { \
1055#include "clang/Basic/Sanitizers.def"
1060 llvm::opt::ArgStringList &CmdArgs,
1061 const char *SCLOptFlag,
1062 const std::vector<std::string> &SCLFiles) {
1063 for (
const auto &SCLPath : SCLFiles) {
1066 CmdArgs.push_back(Args.MakeArgString(SCLOpt));
1071 const llvm::opt::ArgList &Args,
1072 llvm::opt::ArgStringList &CmdArgs,
1073 StringRef SymbolName) {
1075 LinkerOptionFlag =
"--linker-option=/include:";
1076 if (TC.
getTriple().getArch() == llvm::Triple::x86) {
1078 LinkerOptionFlag +=
'_';
1080 LinkerOptionFlag += SymbolName;
1081 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
1085 for (
auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End;
1087 auto It = std::find(Start, End, StringRef(
"+mte"));
1090 if (It > Start && *std::prev(It) == StringRef(
"-target-feature"))
1098 llvm::opt::ArgStringList &CmdArgs,
1106 bool GPUSanitize =
false;
1108 if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
1117 std::pair<int, const char *> CoverageFlags[] = {
1118 std::make_pair(
CoverageFunc,
"-fsanitize-coverage-type=1"),
1119 std::make_pair(
CoverageBB,
"-fsanitize-coverage-type=2"),
1120 std::make_pair(
CoverageEdge,
"-fsanitize-coverage-type=3"),
1129 "-fsanitize-coverage-trace-pc-guard"),
1131 "-fsanitize-coverage-inline-8bit-counters"),
1133 "-fsanitize-coverage-inline-bool-flag"),
1140 for (
auto F : CoverageFlags) {
1141 if (CoverageFeatures & F.first)
1142 CmdArgs.push_back(F.second);
1145 Args, CmdArgs,
"-fsanitize-coverage-allowlist=", CoverageAllowlistFiles);
1147 CoverageIgnorelistFiles);
1152 const std::pair<int, std::string> BinaryMetadataFlags[] = {
1156 for (
const auto &F : BinaryMetadataFlags) {
1157 if (BinaryMetadataFeatures & F.first)
1159 Args.MakeArgString(
"-fexperimental-sanitize-metadata=" + F.second));
1162 "-fexperimental-sanitize-metadata-ignorelist=",
1163 BinaryMetadataIgnorelistFiles);
1170 Args.MakeArgString(
"--dependent-lib=" +
1173 CmdArgs.push_back(Args.MakeArgString(
1174 "--dependent-lib=" +
1178 CmdArgs.push_back(Args.MakeArgString(
1185 CmdArgs.push_back(Args.MakeArgString(
1190 if (Sanitizers.
empty())
1192 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize=" +
toString(Sanitizers)));
1194 if (!RecoverableSanitizers.
empty())
1195 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-recover=" +
1198 if (!TrapSanitizers.
empty())
1200 Args.MakeArgString(
"-fsanitize-trap=" +
toString(TrapSanitizers)));
1203 "-fsanitize-ignorelist=", UserIgnorelistFiles);
1205 "-fsanitize-system-ignorelist=", SystemIgnorelistFiles);
1207 if (MsanTrackOrigins)
1208 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-memory-track-origins=" +
1209 Twine(MsanTrackOrigins)));
1211 if (MsanUseAfterDtor)
1212 CmdArgs.push_back(
"-fsanitize-memory-use-after-dtor");
1214 if (!MsanParamRetval)
1215 CmdArgs.push_back(
"-fno-sanitize-memory-param-retval");
1218 if (!TsanMemoryAccess) {
1219 CmdArgs.push_back(
"-mllvm");
1220 CmdArgs.push_back(
"-tsan-instrument-memory-accesses=0");
1221 CmdArgs.push_back(
"-mllvm");
1222 CmdArgs.push_back(
"-tsan-instrument-memintrinsics=0");
1224 if (!TsanFuncEntryExit) {
1225 CmdArgs.push_back(
"-mllvm");
1226 CmdArgs.push_back(
"-tsan-instrument-func-entry-exit=0");
1229 CmdArgs.push_back(
"-mllvm");
1230 CmdArgs.push_back(
"-tsan-instrument-atomics=0");
1233 if (HwasanUseAliases) {
1234 CmdArgs.push_back(
"-mllvm");
1235 CmdArgs.push_back(
"-hwasan-experimental-use-page-aliases=1");
1239 CmdArgs.push_back(
"-fsanitize-cfi-cross-dso");
1241 if (CfiICallGeneralizePointers)
1242 CmdArgs.push_back(
"-fsanitize-cfi-icall-generalize-pointers");
1244 if (CfiICallNormalizeIntegers)
1245 CmdArgs.push_back(
"-fsanitize-cfi-icall-experimental-normalize-integers");
1247 if (CfiCanonicalJumpTables)
1248 CmdArgs.push_back(
"-fsanitize-cfi-canonical-jump-tables");
1251 CmdArgs.push_back(
"-fsanitize-stats");
1254 CmdArgs.push_back(
"-fsanitize-minimal-runtime");
1256 if (AsanFieldPadding)
1257 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-address-field-padding=" +
1258 Twine(AsanFieldPadding)));
1260 if (AsanUseAfterScope)
1261 CmdArgs.push_back(
"-fsanitize-address-use-after-scope");
1263 if (AsanPoisonCustomArrayCookie)
1264 CmdArgs.push_back(
"-fsanitize-address-poison-custom-array-cookie");
1266 if (AsanGlobalsDeadStripping)
1267 CmdArgs.push_back(
"-fsanitize-address-globals-dead-stripping");
1269 if (!AsanUseOdrIndicator)
1270 CmdArgs.push_back(
"-fno-sanitize-address-use-odr-indicator");
1272 if (AsanInvalidPointerCmp) {
1273 CmdArgs.push_back(
"-mllvm");
1274 CmdArgs.push_back(
"-asan-detect-invalid-pointer-cmp");
1277 if (AsanInvalidPointerSub) {
1278 CmdArgs.push_back(
"-mllvm");
1279 CmdArgs.push_back(
"-asan-detect-invalid-pointer-sub");
1282 if (AsanOutlineInstrumentation) {
1283 CmdArgs.push_back(
"-mllvm");
1284 CmdArgs.push_back(
"-asan-instrumentation-with-call-threshold=0");
1291 CmdArgs.push_back(
"-mllvm");
1292 CmdArgs.push_back(
"-asan-instrumentation-with-call-threshold=0");
1293 CmdArgs.push_back(
"-mllvm");
1294 CmdArgs.push_back(
"-asan-max-inline-poisoning-size=0");
1299 if (AsanDtorKind != llvm::AsanDtorKind::Invalid) {
1300 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-address-destructor=" +
1304 if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
1305 CmdArgs.push_back(Args.MakeArgString(
1306 "-fsanitize-address-use-after-return=" +
1310 if (!HwasanAbi.empty()) {
1311 CmdArgs.push_back(
"-default-function-attr");
1312 CmdArgs.push_back(Args.MakeArgString(
"hwasan-abi=" + HwasanAbi));
1315 if (Sanitizers.
has(SanitizerKind::HWAddress) && !HwasanUseAliases) {
1316 CmdArgs.push_back(
"-target-feature");
1317 CmdArgs.push_back(
"+tagged-globals");
1325 if (Sanitizers.
has(SanitizerKind::Memory) ||
1326 Sanitizers.
has(SanitizerKind::Address))
1327 CmdArgs.push_back(
"-fno-assume-sane-operator-new");
1334 if (Sanitizers.
has(SanitizerKind::FuzzerNoLink)) {
1335 CmdArgs.push_back(
"-fno-builtin-bcmp");
1336 CmdArgs.push_back(
"-fno-builtin-memcmp");
1337 CmdArgs.push_back(
"-fno-builtin-strncmp");
1338 CmdArgs.push_back(
"-fno-builtin-strcmp");
1339 CmdArgs.push_back(
"-fno-builtin-strncasecmp");
1340 CmdArgs.push_back(
"-fno-builtin-strcasecmp");
1341 CmdArgs.push_back(
"-fno-builtin-strstr");
1342 CmdArgs.push_back(
"-fno-builtin-strcasestr");
1343 CmdArgs.push_back(
"-fno-builtin-memmem");
1349 !Args.hasArg(options::OPT_fvisibility_EQ)) {
1350 TC.
getDriver().
Diag(clang::diag::err_drv_argument_only_allowed_with)
1356 if (Sanitizers.
has(SanitizerKind::MemtagStack) &&
1358 TC.
getDriver().
Diag(diag::err_stack_tagging_requires_hardware_feature);
1362 bool DiagnoseErrors) {
1363 assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
1364 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
1365 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
1366 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
1367 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
1368 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) &&
1369 "Invalid argument in parseArgValues!");
1371 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1372 const char *
Value = A->getValue(i);
1375 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
1376 0 == strcmp(
"all",
Value))
1383 else if (DiagnoseErrors)
1384 D.
Diag(clang::diag::err_drv_unsupported_option_argument)
1385 << A->getSpelling() <<
Value;
1391 bool DiagnoseErrors) {
1392 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
1393 A->getOption().matches(options::OPT_fno_sanitize_coverage));
1395 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1396 const char *
Value = A->getValue(i);
1397 int F = llvm::StringSwitch<int>(
Value)
1418 if (F == 0 && DiagnoseErrors)
1419 D.
Diag(clang::diag::err_drv_unsupported_option_argument)
1420 << A->getSpelling() <<
Value;
1427 bool DiagnoseErrors) {
1429 A->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ) ||
1430 A->getOption().matches(
1431 options::OPT_fno_experimental_sanitize_metadata_EQ));
1433 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1434 const char *
Value = A->getValue(i);
1435 int F = llvm::StringSwitch<int>(
Value)
1441 if (F == 0 && DiagnoseErrors)
1442 D.
Diag(clang::diag::err_drv_unsupported_option_argument)
1443 << A->getSpelling() <<
Value;
1451 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
1454 const auto *Arg = *I;
1455 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
1458 if (AddKinds & Mask)
1460 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
1463 Mask &= ~RemoveKinds;
1466 llvm_unreachable(
"arg list didn't provide expected value");
1470 assert(A->getOption().matches(options::OPT_fsanitize_EQ) &&
1471 "Invalid argument in describeSanitizerArg!");
1473 std::string Sanitizers;
1474 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1478 if (!Sanitizers.empty())
1480 Sanitizers += A->getValue(i);
1484 assert(!Sanitizers.empty() &&
"arg didn't provide expected value");
1485 return "-fsanitize=" + Sanitizers;
static void addDefaultIgnorelists(const Driver &D, SanitizerMask Kinds, std::vector< std::string > &IgnorelistFiles, bool DiagnoseErrors)
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 SanitizerMask parseSanitizeTrapArgs(const Driver &D, const llvm::opt::ArgList &Args, bool DiagnoseErrors)
static void addIncludeLinkerOption(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, StringRef SymbolName)
static bool hasTargetFeatureMTE(const llvm::opt::ArgStringList &CmdArgs)
static const SanitizerMask SupportsCoverage
static const SanitizerMask CFIClasses
static int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A, bool DiagnoseErrors)
Parse -f(no-)?sanitize-metadata= flag values, diagnosing any invalid components.
static const SanitizerMask TrappingSupported
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 NeedsUnwindTables
static const SanitizerMask RequiresPIE
static void addSpecialCaseListOpt(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, const char *SCLOptFlag, const std::vector< std::string > &SCLFiles)
static const SanitizerMask NotAllowedWithMinimalRuntime
static const SanitizerMask AlwaysRecoverable
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...
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static const SanitizerMask NeedsUbsanCxxRt
static const SanitizerMask TrappingDefault
static const SanitizerMask CompatibleWithMinimalRuntime
static const SanitizerMask Unrecoverable
static const SanitizerMask RecoverableByDefault
static const SanitizerMask NeedsLTO
static SanitizerMask setGroupBits(SanitizerMask Kinds)
Sets group bits for every group that has at least one representative already enabled in Kinds.
static const SanitizerMask NeedsUbsanRt
static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A, bool DiagnoseErrors)
Parse -f(no-)?sanitize-coverage= flag values, diagnosing any invalid components.
static void validateSpecialCaseListFormat(const Driver &D, std::vector< std::string > &SCLFiles, unsigned MalformedSCLErrorDiagID, bool DiagnoseErrors)
static const SanitizerMask NotAllowedWithTrap
static void parseSpecialCaseListArg(const Driver &D, const llvm::opt::ArgList &Args, std::vector< std::string > &SCLFiles, llvm::opt::OptSpecifier SCLOptionID, llvm::opt::OptSpecifier NoSCLOptionID, unsigned MalformedSCLErrorDiagID, bool DiagnoseErrors)
Parse -f(no-)?sanitize-(coverage-)?(allow|ignore)list argument's values, diagnosing any invalid file ...
@ CoverageInline8bitCounters
Defines the clang::SanitizerKind enum.
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
DiagnosticBuilder Diag(unsigned DiagID) const
std::string ResourceDir
The path to the compiler resource directory.
llvm::vfs::FileSystem & getVFS() const
bool isUsingLTO(bool IsOffload=false) const
Returns true if we are performing any kind of LTO.
bool CCCIsCXX() const
Whether the driver should follow g++ like behavior.
bool needsFuzzerInterceptors() const
bool needsStatsRt() const
bool needsCfiDiagRt() const
bool needsUbsanRt() const
SanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, bool DiagnoseErrors=true)
Parses the sanitizer arguments from an argument list.
bool needsHwasanRt() const
bool requiresMinimalRuntime() const
bool needsUnwindTables() const
bool needsDfsanRt() const
bool needsScudoRt() const
void addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, types::ID InputType) const
bool isCXX(ID Id)
isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers).
StringRef AsanDtorKindToString(llvm::AsanDtorKind kind)
SanitizerMask expandSanitizerGroups(SanitizerMask Kinds)
For each sanitizer group bit set in Kinds, set the bits for sanitizers this group enables.
SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups)
Parse a single value from a -fsanitize= or -fno-sanitize= value list.
llvm::AsanDtorKind AsanDtorKindFromString(StringRef kind)
llvm::AsanDetectStackUseAfterReturnMode AsanDetectStackUseAfterReturnModeFromString(StringRef modeStr)
StringRef AsanDetectStackUseAfterReturnModeToString(llvm::AsanDetectStackUseAfterReturnMode mode)
bool empty() const
Returns true if no sanitizers are enabled.
bool has(SanitizerMask K) const
Check if a certain (single) sanitizer is enabled.
SanitizerMask Mask
Bitmask of enabled sanitizers.
bool hasOneOf(SanitizerMask K) const
Check if one or more sanitizers are enabled.