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::Function | SanitizerKind::KCFI;
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 | SanitizerKind::KCFI;
113 bool DiagnoseErrors);
118 bool DiagnoseErrors);
123 bool DiagnoseErrors);
130 const llvm::opt::ArgList &Args,
147 const llvm::opt::ArgList &Args) {
150 return Args.hasFlagNoClaim(options::OPT_mexecute_only,
151 options::OPT_mno_execute_only,
false);
155 std::vector<std::string> &SCLFiles,
156 unsigned MalformedSCLErrorDiagID,
157 bool DiagnoseErrors) {
158 if (SCLFiles.empty())
162 std::unique_ptr<llvm::SpecialCaseList> SCL(
163 llvm::SpecialCaseList::create(SCLFiles, D.
getVFS(), BLError));
164 if (!SCL.get() && DiagnoseErrors)
165 D.
Diag(MalformedSCLErrorDiagID) << BLError;
169 std::vector<std::string> &IgnorelistFiles,
170 bool DiagnoseErrors) {
174 } Ignorelists[] = {{
"asan_ignorelist.txt", SanitizerKind::Address},
175 {
"hwasan_ignorelist.txt", SanitizerKind::HWAddress},
176 {
"memtag_ignorelist.txt", SanitizerKind::MemTag},
177 {
"msan_ignorelist.txt", SanitizerKind::Memory},
178 {
"tsan_ignorelist.txt", SanitizerKind::Thread},
179 {
"dfsan_abilist.txt", SanitizerKind::DataFlow},
180 {
"cfi_ignorelist.txt", SanitizerKind::CFI},
181 {
"ubsan_ignorelist.txt",
182 SanitizerKind::Undefined | SanitizerKind::Integer |
183 SanitizerKind::Nullability |
184 SanitizerKind::FloatDivideByZero}};
186 for (
auto BL : Ignorelists) {
187 if (!(Kinds & BL.Mask))
191 llvm::sys::path::append(Path,
"share", BL.File);
192 if (D.
getVFS().exists(Path))
193 IgnorelistFiles.push_back(std::string(Path));
194 else if (BL.Mask == SanitizerKind::CFI && DiagnoseErrors)
197 D.
Diag(clang::diag::err_drv_missing_sanitizer_ignorelist) << Path;
200 D, IgnorelistFiles, clang::diag::err_drv_malformed_sanitizer_ignorelist,
207 const llvm::opt::ArgList &Args,
208 std::vector<std::string> &SCLFiles,
209 llvm::opt::OptSpecifier SCLOptionID,
210 llvm::opt::OptSpecifier NoSCLOptionID,
211 unsigned MalformedSCLErrorDiagID,
212 bool DiagnoseErrors) {
213 for (
const auto *Arg : Args) {
215 if (Arg->getOption().matches(SCLOptionID)) {
217 std::string SCLPath = Arg->getValue();
218 if (D.
getVFS().exists(SCLPath)) {
219 SCLFiles.push_back(SCLPath);
220 }
else if (DiagnoseErrors) {
221 D.
Diag(clang::diag::err_drv_no_such_file) << SCLPath;
224 }
else if (Arg->getOption().matches(NoSCLOptionID)) {
236#define SANITIZER(NAME, ID)
237#define SANITIZER_GROUP(NAME, ID, ALIAS) \
238 if (Kinds & SanitizerKind::ID) \
239 Kinds |= SanitizerKind::ID##Group;
240#include "clang/Basic/Sanitizers.def"
245 const llvm::opt::ArgList &Args,
246 bool DiagnoseErrors) {
253 for (
const llvm::opt::Arg *Arg : llvm::reverse(Args)) {
254 if (Arg->getOption().matches(options::OPT_fsanitize_trap_EQ)) {
258 SanitizerMask InvalidValues = Add & ~TrappingSupportedWithGroups;
259 if (InvalidValues && DiagnoseErrors) {
261 S.Mask = InvalidValues;
262 D.
Diag(diag::err_drv_unsupported_option_argument)
263 << Arg->getSpelling() <<
toString(S);
266 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) {
276 return TrappingKinds;
295 return !(Sanitizers.
Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
296 CfiCrossDso && !ImplicitCfiRuntime;
300 return (Sanitizers.
Mask & SanitizerKind::CFI & ~TrapSanitizers.
Mask) &&
301 CfiCrossDso && !ImplicitCfiRuntime;
315 const llvm::opt::ArgList &Args,
316 bool DiagnoseErrors) {
330 CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
331 options::OPT_fno_sanitize_cfi_cross_dso,
false);
340 Args.hasFlag(options::OPT_fsanitize_minimal_runtime,
341 options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime);
344 Arg *OptLevel = Args.getLastArg(options::OPT_O_Group);
345 bool RemoveObjectSizeAtO0 =
346 !OptLevel || OptLevel->getOption().matches(options::OPT_O0);
348 for (
const llvm::opt::Arg *Arg : llvm::reverse(Args)) {
349 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
353 if (RemoveObjectSizeAtO0) {
354 AllRemove |= SanitizerKind::ObjectSize;
358 if ((Add & SanitizerKind::ObjectSize) && DiagnoseErrors)
359 D.
Diag(diag::warn_drv_object_size_disabled_O0)
360 << Arg->getAsString(Args);
371 Add & InvalidTrappingKinds & ~DiagnosedKinds) {
372 if (DiagnoseErrors) {
374 D.
Diag(diag::err_drv_argument_not_allowed_with)
375 << Desc <<
"-fsanitize-trap=undefined";
377 DiagnosedKinds |= KindsToDiagnose;
379 Add &= ~InvalidTrappingKinds;
381 if (MinimalRuntime) {
384 if (DiagnoseErrors) {
386 D.
Diag(diag::err_drv_argument_not_allowed_with)
387 << Desc <<
"-fsanitize-minimal-runtime";
389 DiagnosedKinds |= KindsToDiagnose;
391 Add &= ~NotAllowedWithMinimalRuntime;
394 if (llvm::opt::Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
395 StringRef CM = A->getValue();
397 (Add & SanitizerKind::Function & ~DiagnosedKinds)) {
399 D.
Diag(diag::err_drv_argument_only_allowed_with)
400 <<
"-fsanitize=function"
403 DiagnosedKinds |= SanitizerKind::Function;
409 const llvm::Triple &Triple = TC.
getTriple();
413 if (DiagnoseErrors) {
415 D.
Diag(diag::err_drv_argument_not_allowed_with)
416 << Desc << Triple.str();
418 DiagnosedKinds |= KindsToDiagnose;
420 Add &= ~NotAllowedWithExecuteOnly;
433 if (CfiCrossDso && (Add & SanitizerKind::CFIMFCall & ~DiagnosedKinds)) {
435 D.
Diag(diag::err_drv_argument_not_allowed_with)
436 <<
"-fsanitize=cfi-mfcall"
437 <<
"-fsanitize-cfi-cross-dso";
439 DiagnosedKinds |= SanitizerKind::CFIMFCall;
442 if (
SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
443 if (DiagnoseErrors) {
445 D.
Diag(diag::err_drv_unsupported_opt_for_target)
448 DiagnosedKinds |= KindsToDiagnose;
456 if (
const llvm::opt::Arg *NoRTTIArg = TC.
getRTTIArg()) {
457 assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) &&
458 "RTTI disabled without -fno-rtti option?");
462 D.
Diag(diag::err_drv_argument_not_allowed_with)
463 <<
"-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
468 D.
Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
472 AllRemove |= SanitizerKind::Vptr;
480 Add &= ~InvalidTrappingKinds;
481 if (MinimalRuntime) {
482 Add &= ~NotAllowedWithMinimalRuntime;
487 Add &= ~NotAllowedWithExecuteOnly;
492 if (Add & SanitizerKind::Fuzzer)
493 Add |= SanitizerKind::FuzzerNoLink;
496 if (Add & SanitizerKind::FuzzerNoLink) {
505 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
512 std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
513 std::make_pair(SanitizerKind::Address,
514 SanitizerKind::Thread | SanitizerKind::Memory),
515 std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory),
516 std::make_pair(SanitizerKind::Leak,
517 SanitizerKind::Thread | SanitizerKind::Memory),
518 std::make_pair(SanitizerKind::KernelAddress,
519 SanitizerKind::Address | SanitizerKind::Leak |
520 SanitizerKind::Thread | SanitizerKind::Memory),
521 std::make_pair(SanitizerKind::HWAddress,
522 SanitizerKind::Address | SanitizerKind::Thread |
523 SanitizerKind::Memory | SanitizerKind::KernelAddress),
524 std::make_pair(SanitizerKind::Scudo,
525 SanitizerKind::Address | SanitizerKind::HWAddress |
526 SanitizerKind::Leak | SanitizerKind::Thread |
527 SanitizerKind::Memory | SanitizerKind::KernelAddress),
528 std::make_pair(SanitizerKind::SafeStack,
530 : SanitizerKind::Leak) |
531 SanitizerKind::Address | SanitizerKind::HWAddress |
532 SanitizerKind::Thread | SanitizerKind::Memory |
533 SanitizerKind::KernelAddress),
534 std::make_pair(SanitizerKind::KernelHWAddress,
535 SanitizerKind::Address | SanitizerKind::HWAddress |
536 SanitizerKind::Leak | SanitizerKind::Thread |
537 SanitizerKind::Memory | SanitizerKind::KernelAddress |
538 SanitizerKind::SafeStack),
539 std::make_pair(SanitizerKind::KernelMemory,
540 SanitizerKind::Address | SanitizerKind::HWAddress |
541 SanitizerKind::Leak | SanitizerKind::Thread |
542 SanitizerKind::Memory | SanitizerKind::KernelAddress |
543 SanitizerKind::Scudo | SanitizerKind::SafeStack),
544 std::make_pair(SanitizerKind::MemTag,
545 SanitizerKind::Address | SanitizerKind::KernelAddress |
546 SanitizerKind::HWAddress |
547 SanitizerKind::KernelHWAddress),
548 std::make_pair(SanitizerKind::KCFI, SanitizerKind::Function)};
554 for (
auto G : IncompatibleGroups) {
556 if ((
Default & Group) && (Kinds & G.second))
570 D.
Diag(diag::err_drv_argument_only_allowed_with)
574 if ((Kinds & SanitizerKind::ShadowCallStack) && TC.
getTriple().isAArch64() &&
575 !llvm::AArch64::isX18ReservedByDefault(TC.
getTriple()) &&
576 !Args.hasArg(options::OPT_ffixed_x18) && DiagnoseErrors) {
577 D.
Diag(diag::err_drv_argument_only_allowed_with)
586 if (~Supported & SanitizerKind::Vptr) {
592 if (KindsToDiagnose) {
594 S.Mask = KindsToDiagnose;
596 D.
Diag(diag::err_drv_unsupported_opt_for_target)
598 Kinds &= ~KindsToDiagnose;
603 for (
auto G : IncompatibleGroups) {
608 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
611 Kinds &= ~Incompatible;
624 for (
const auto *Arg : Args) {
625 if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
632 SetToDiagnose.
Mask |= KindsToDiagnose;
634 D.
Diag(diag::err_drv_unsupported_option_argument)
635 << Arg->getSpelling() <<
toString(SetToDiagnose);
636 DiagnosedUnrecoverableKinds |= KindsToDiagnose;
640 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {
647 SetToDiagnose.
Mask |= KindsToDiagnose;
649 D.
Diag(diag::err_drv_unsupported_option_argument)
650 << Arg->getSpelling() <<
toString(SetToDiagnose);
651 DiagnosedAlwaysRecoverableKinds |= KindsToDiagnose;
653 RecoverableKinds &= ~expandSanitizerGroups(Remove);
657 RecoverableKinds &= Kinds;
658 RecoverableKinds &= ~Unrecoverable;
660 TrappingKinds &= Kinds;
661 RecoverableKinds &= ~TrappingKinds;
666 if (!Args.hasArgNoClaim(options::OPT_fno_sanitize_ignorelist))
672 D, Args, UserIgnorelistFiles, options::OPT_fsanitize_ignorelist_EQ,
673 options::OPT_fno_sanitize_ignorelist,
674 clang::diag::err_drv_malformed_sanitizer_ignorelist, DiagnoseErrors);
677 if (AllAddedKinds & SanitizerKind::Memory) {
679 Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
680 options::OPT_fno_sanitize_memory_track_origins)) {
681 if (!A->getOption().matches(
682 options::OPT_fno_sanitize_memory_track_origins)) {
683 StringRef S = A->getValue();
684 if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
685 MsanTrackOrigins > 2) {
687 D.
Diag(clang::diag::err_drv_invalid_value)
688 << A->getAsString(Args) << S;
692 MsanUseAfterDtor = Args.hasFlag(
693 options::OPT_fsanitize_memory_use_after_dtor,
694 options::OPT_fno_sanitize_memory_use_after_dtor, MsanUseAfterDtor);
695 MsanParamRetval = Args.hasFlag(
696 options::OPT_fsanitize_memory_param_retval,
697 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
698 }
else if (AllAddedKinds & SanitizerKind::KernelMemory) {
699 MsanUseAfterDtor =
false;
700 MsanParamRetval = Args.hasFlag(
701 options::OPT_fsanitize_memory_param_retval,
702 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
704 MsanUseAfterDtor =
false;
705 MsanParamRetval =
false;
708 if (AllAddedKinds & SanitizerKind::MemTag) {
710 Args.getLastArgValue(options::OPT_fsanitize_memtag_mode_EQ,
"sync");
711 if (S ==
"async" || S ==
"sync") {
712 MemtagMode = S.str();
714 D.
Diag(clang::diag::err_drv_invalid_value_with_suggestion)
715 <<
"-fsanitize-memtag-mode=" << S <<
"{async, sync}";
720 if (AllAddedKinds & SanitizerKind::Thread) {
721 TsanMemoryAccess = Args.hasFlag(
722 options::OPT_fsanitize_thread_memory_access,
723 options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess);
724 TsanFuncEntryExit = Args.hasFlag(
725 options::OPT_fsanitize_thread_func_entry_exit,
726 options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit);
728 Args.hasFlag(options::OPT_fsanitize_thread_atomics,
729 options::OPT_fno_sanitize_thread_atomics, TsanAtomics);
732 if (AllAddedKinds & SanitizerKind::CFI) {
735 NeedPIE |= CfiCrossDso;
736 CfiICallGeneralizePointers =
737 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
739 CfiICallNormalizeIntegers =
740 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
742 if (CfiCrossDso && CfiICallGeneralizePointers && DiagnoseErrors)
743 D.
Diag(diag::err_drv_argument_not_allowed_with)
744 <<
"-fsanitize-cfi-cross-dso"
745 <<
"-fsanitize-cfi-icall-generalize-pointers";
747 CfiCanonicalJumpTables =
748 Args.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables,
749 options::OPT_fno_sanitize_cfi_canonical_jump_tables,
true);
752 if (AllAddedKinds & SanitizerKind::KCFI) {
753 CfiICallNormalizeIntegers =
754 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
756 if (AllAddedKinds & SanitizerKind::CFI && DiagnoseErrors)
757 D.
Diag(diag::err_drv_argument_not_allowed_with)
762 Stats = Args.hasFlag(options::OPT_fsanitize_stats,
763 options::OPT_fno_sanitize_stats,
false);
765 if (MinimalRuntime) {
768 if (IncompatibleMask && DiagnoseErrors)
769 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
770 <<
"-fsanitize-minimal-runtime"
773 SanitizerMask NonTrappingCfi = Kinds & SanitizerKind::CFI & ~TrappingKinds;
774 if (NonTrappingCfi && DiagnoseErrors)
775 D.
Diag(clang::diag::err_drv_argument_only_allowed_with)
776 <<
"fsanitize-minimal-runtime"
777 <<
"fsanitize-trap=cfi";
782 for (
const auto *Arg : Args) {
783 if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
784 int LegacySanitizeCoverage;
785 if (Arg->getNumValues() == 1 &&
786 !StringRef(Arg->getValue(0))
787 .getAsInteger(0, LegacySanitizeCoverage)) {
788 CoverageFeatures = 0;
790 if (LegacySanitizeCoverage != 0 && DiagnoseErrors) {
791 D.
Diag(diag::warn_drv_deprecated_arg)
792 << Arg->getAsString(Args) <<
"-fsanitize-coverage=trace-pc-guard";
803 CoverageFeatures = 0;
805 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
807 CoverageFeatures &= ~parseCoverageFeatures(D, Arg, DiagnoseErrors);
811 if (DiagnoseErrors) {
813 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
814 <<
"-fsanitize-coverage=func"
815 <<
"-fsanitize-coverage=bb";
817 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
818 <<
"-fsanitize-coverage=func"
819 <<
"-fsanitize-coverage=edge";
821 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
822 <<
"-fsanitize-coverage=bb"
823 <<
"-fsanitize-coverage=edge";
827 D.
Diag(clang::diag::warn_drv_deprecated_arg)
828 <<
"-fsanitize-coverage=trace-bb"
829 <<
"-fsanitize-coverage=trace-pc-guard";
831 D.
Diag(clang::diag::warn_drv_deprecated_arg)
832 <<
"-fsanitize-coverage=8bit-counters"
833 <<
"-fsanitize-coverage=trace-pc-guard";
841 if ((CoverageFeatures & InsertionPointTypes) &&
842 !(CoverageFeatures & InstrumentationTypes) && DiagnoseErrors) {
843 D.
Diag(clang::diag::warn_drv_deprecated_arg)
844 <<
"-fsanitize-coverage=[func|bb|edge]"
845 <<
"-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc],["
850 if (!(CoverageFeatures & InsertionPointTypes)) {
851 if (CoverageFeatures &
864 if (CoverageFeatures) {
866 D, Args, CoverageAllowlistFiles,
867 options::OPT_fsanitize_coverage_allowlist, OptSpecifier(),
868 clang::diag::err_drv_malformed_sanitizer_coverage_allowlist,
871 D, Args, CoverageIgnorelistFiles,
872 options::OPT_fsanitize_coverage_ignorelist, OptSpecifier(),
873 clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist,
878 for (
const auto *Arg :
879 Args.filtered(options::OPT_fexperimental_sanitize_metadata_EQ,
880 options::OPT_fno_experimental_sanitize_metadata_EQ)) {
881 if (Arg->getOption().matches(
882 options::OPT_fexperimental_sanitize_metadata_EQ)) {
884 BinaryMetadataFeatures |=
888 BinaryMetadataFeatures &=
889 ~parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);
894 if (BinaryMetadataFeatures) {
896 D, Args, BinaryMetadataIgnorelistFiles,
897 options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ,
899 clang::diag::err_drv_malformed_sanitizer_metadata_ignorelist,
904 Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan,
908 ImplicitCfiRuntime = TC.
getTriple().isAndroid();
910 if (AllAddedKinds & SanitizerKind::Address) {
913 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
914 StringRef S = A->getValue();
916 if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
917 AsanFieldPadding > 2) &&
919 D.
Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
923 if (Arg *WindowsDebugRTArg =
924 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
925 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
926 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
927 switch (WindowsDebugRTArg->getOption().getID()) {
928 case options::OPT__SLASH_MTd:
929 case options::OPT__SLASH_MDd:
930 case options::OPT__SLASH_LDd:
931 if (DiagnoseErrors) {
932 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
933 << WindowsDebugRTArg->getAsString(Args)
935 D.
Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
940 StableABI = Args.hasFlag(options::OPT_fsanitize_stable_abi,
941 options::OPT_fno_sanitize_stable_abi,
false);
943 AsanUseAfterScope = Args.hasFlag(
944 options::OPT_fsanitize_address_use_after_scope,
945 options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);
947 AsanPoisonCustomArrayCookie = Args.hasFlag(
948 options::OPT_fsanitize_address_poison_custom_array_cookie,
949 options::OPT_fno_sanitize_address_poison_custom_array_cookie,
950 AsanPoisonCustomArrayCookie);
952 AsanOutlineInstrumentation =
953 Args.hasFlag(options::OPT_fsanitize_address_outline_instrumentation,
954 options::OPT_fno_sanitize_address_outline_instrumentation,
955 AsanOutlineInstrumentation);
957 AsanGlobalsDeadStripping = Args.hasFlag(
958 options::OPT_fsanitize_address_globals_dead_stripping,
959 options::OPT_fno_sanitize_address_globals_dead_stripping,
true);
965 AsanUseOdrIndicator =
966 Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
967 options::OPT_fno_sanitize_address_use_odr_indicator,
970 if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) {
971 AsanInvalidPointerCmp =
true;
974 if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) {
975 AsanInvalidPointerSub =
true;
979 (Args.hasArg(options::OPT_mkernel) ||
980 Args.hasArg(options::OPT_fapple_kext))) {
981 AsanDtorKind = llvm::AsanDtorKind::None;
984 if (
const auto *Arg =
985 Args.getLastArg(options::OPT_sanitize_address_destructor_EQ)) {
987 if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid && DiagnoseErrors) {
988 TC.
getDriver().
Diag(clang::diag::err_drv_unsupported_option_argument)
989 << Arg->getSpelling() << Arg->getValue();
991 AsanDtorKind = parsedAsanDtorKind;
994 if (
const auto *Arg = Args.getLastArg(
995 options::OPT_sanitize_address_use_after_return_EQ)) {
996 auto parsedAsanUseAfterReturn =
998 if (parsedAsanUseAfterReturn ==
999 llvm::AsanDetectStackUseAfterReturnMode::Invalid &&
1001 TC.
getDriver().
Diag(clang::diag::err_drv_unsupported_option_argument)
1002 << Arg->getSpelling() << Arg->getValue();
1004 AsanUseAfterReturn = parsedAsanUseAfterReturn;
1008 AsanUseAfterScope =
false;
1011 SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract;
1012 if ((AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) &&
1014 TC.
getDriver().
Diag(clang::diag::err_drv_argument_only_allowed_with)
1016 SanitizerKind::PointerCompare |
1017 SanitizerKind::PointerSubtract)
1018 <<
"-fsanitize=address";
1022 if (AllAddedKinds & SanitizerKind::HWAddress) {
1023 if (Arg *HwasanAbiArg =
1024 Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {
1025 HwasanAbi = HwasanAbiArg->getValue();
1026 if (HwasanAbi !=
"platform" && HwasanAbi !=
"interceptor" &&
1028 D.
Diag(clang::diag::err_drv_invalid_value)
1029 << HwasanAbiArg->getAsString(Args) << HwasanAbi;
1031 HwasanAbi =
"interceptor";
1033 if (TC.
getTriple().getArch() == llvm::Triple::x86_64)
1034 HwasanUseAliases = Args.hasFlag(
1035 options::OPT_fsanitize_hwaddress_experimental_aliasing,
1036 options::OPT_fno_sanitize_hwaddress_experimental_aliasing,
1040 if (AllAddedKinds & SanitizerKind::SafeStack) {
1047 Args.hasFlag(options::OPT_fsanitize_link_runtime,
1048 options::OPT_fno_sanitize_link_runtime, LinkRuntimes);
1051 LinkCXXRuntimes = Args.hasArg(options::OPT_fsanitize_link_cxx_runtime,
1052 options::OPT_fno_sanitize_link_cxx_runtime,
1056 NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile,
1057 options::OPT_fmemory_profile_EQ,
1058 options::OPT_fno_memory_profile,
false);
1061 Sanitizers.
Mask |= Kinds;
1062 RecoverableSanitizers.
Mask |= RecoverableKinds;
1063 TrapSanitizers.
Mask |= TrappingKinds;
1064 assert(!(RecoverableKinds & TrappingKinds) &&
1065 "Overlap between recoverable and trapping sanitizers");
1070#define SANITIZER(NAME, ID) \
1071 if (Sanitizers.has(SanitizerKind::ID)) { \
1076#include "clang/Basic/Sanitizers.def"
1081 llvm::opt::ArgStringList &CmdArgs,
1082 const char *SCLOptFlag,
1083 const std::vector<std::string> &SCLFiles) {
1084 for (
const auto &SCLPath : SCLFiles) {
1087 CmdArgs.push_back(Args.MakeArgString(SCLOpt));
1092 const llvm::opt::ArgList &Args,
1093 llvm::opt::ArgStringList &CmdArgs,
1094 StringRef SymbolName) {
1096 LinkerOptionFlag =
"--linker-option=/include:";
1097 if (TC.
getTriple().getArch() == llvm::Triple::x86) {
1099 LinkerOptionFlag +=
'_';
1101 LinkerOptionFlag += SymbolName;
1102 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
1106 for (
auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End;
1108 auto It = std::find(Start, End, StringRef(
"+mte"));
1111 if (It > Start && *std::prev(It) == StringRef(
"-target-feature"))
1119 llvm::opt::ArgStringList &CmdArgs,
1127 bool GPUSanitize =
false;
1129 if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
1138 std::pair<int, const char *> CoverageFlags[] = {
1139 std::make_pair(
CoverageFunc,
"-fsanitize-coverage-type=1"),
1140 std::make_pair(
CoverageBB,
"-fsanitize-coverage-type=2"),
1141 std::make_pair(
CoverageEdge,
"-fsanitize-coverage-type=3"),
1150 "-fsanitize-coverage-trace-pc-guard"),
1152 "-fsanitize-coverage-inline-8bit-counters"),
1154 "-fsanitize-coverage-inline-bool-flag"),
1161 for (
auto F : CoverageFlags) {
1162 if (CoverageFeatures & F.first)
1163 CmdArgs.push_back(F.second);
1166 Args, CmdArgs,
"-fsanitize-coverage-allowlist=", CoverageAllowlistFiles);
1168 CoverageIgnorelistFiles);
1173 const std::pair<int, std::string> BinaryMetadataFlags[] = {
1177 for (
const auto &F : BinaryMetadataFlags) {
1178 if (BinaryMetadataFeatures & F.first)
1180 Args.MakeArgString(
"-fexperimental-sanitize-metadata=" + F.second));
1183 "-fexperimental-sanitize-metadata-ignorelist=",
1184 BinaryMetadataIgnorelistFiles);
1191 Args.MakeArgString(
"--dependent-lib=" +
1194 CmdArgs.push_back(Args.MakeArgString(
1195 "--dependent-lib=" +
1199 CmdArgs.push_back(Args.MakeArgString(
1206 CmdArgs.push_back(Args.MakeArgString(
1211 if (Sanitizers.
empty())
1213 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize=" +
toString(Sanitizers)));
1215 if (!RecoverableSanitizers.
empty())
1216 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-recover=" +
1219 if (!TrapSanitizers.
empty())
1221 Args.MakeArgString(
"-fsanitize-trap=" +
toString(TrapSanitizers)));
1224 "-fsanitize-ignorelist=", UserIgnorelistFiles);
1226 "-fsanitize-system-ignorelist=", SystemIgnorelistFiles);
1228 if (MsanTrackOrigins)
1229 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-memory-track-origins=" +
1230 Twine(MsanTrackOrigins)));
1232 if (MsanUseAfterDtor)
1233 CmdArgs.push_back(
"-fsanitize-memory-use-after-dtor");
1235 if (!MsanParamRetval)
1236 CmdArgs.push_back(
"-fno-sanitize-memory-param-retval");
1239 if (!TsanMemoryAccess) {
1240 CmdArgs.push_back(
"-mllvm");
1241 CmdArgs.push_back(
"-tsan-instrument-memory-accesses=0");
1242 CmdArgs.push_back(
"-mllvm");
1243 CmdArgs.push_back(
"-tsan-instrument-memintrinsics=0");
1245 if (!TsanFuncEntryExit) {
1246 CmdArgs.push_back(
"-mllvm");
1247 CmdArgs.push_back(
"-tsan-instrument-func-entry-exit=0");
1250 CmdArgs.push_back(
"-mllvm");
1251 CmdArgs.push_back(
"-tsan-instrument-atomics=0");
1254 if (HwasanUseAliases) {
1255 CmdArgs.push_back(
"-mllvm");
1256 CmdArgs.push_back(
"-hwasan-experimental-use-page-aliases=1");
1260 CmdArgs.push_back(
"-fsanitize-cfi-cross-dso");
1262 if (CfiICallGeneralizePointers)
1263 CmdArgs.push_back(
"-fsanitize-cfi-icall-generalize-pointers");
1265 if (CfiICallNormalizeIntegers)
1266 CmdArgs.push_back(
"-fsanitize-cfi-icall-experimental-normalize-integers");
1268 if (CfiCanonicalJumpTables)
1269 CmdArgs.push_back(
"-fsanitize-cfi-canonical-jump-tables");
1272 CmdArgs.push_back(
"-fsanitize-stats");
1275 CmdArgs.push_back(
"-fsanitize-minimal-runtime");
1277 if (AsanFieldPadding)
1278 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-address-field-padding=" +
1279 Twine(AsanFieldPadding)));
1281 if (AsanUseAfterScope)
1282 CmdArgs.push_back(
"-fsanitize-address-use-after-scope");
1284 if (AsanPoisonCustomArrayCookie)
1285 CmdArgs.push_back(
"-fsanitize-address-poison-custom-array-cookie");
1287 if (AsanGlobalsDeadStripping)
1288 CmdArgs.push_back(
"-fsanitize-address-globals-dead-stripping");
1290 if (!AsanUseOdrIndicator)
1291 CmdArgs.push_back(
"-fno-sanitize-address-use-odr-indicator");
1293 if (AsanInvalidPointerCmp) {
1294 CmdArgs.push_back(
"-mllvm");
1295 CmdArgs.push_back(
"-asan-detect-invalid-pointer-cmp");
1298 if (AsanInvalidPointerSub) {
1299 CmdArgs.push_back(
"-mllvm");
1300 CmdArgs.push_back(
"-asan-detect-invalid-pointer-sub");
1303 if (AsanOutlineInstrumentation) {
1304 CmdArgs.push_back(
"-mllvm");
1305 CmdArgs.push_back(
"-asan-instrumentation-with-call-threshold=0");
1312 CmdArgs.push_back(
"-mllvm");
1313 CmdArgs.push_back(
"-asan-instrumentation-with-call-threshold=0");
1314 CmdArgs.push_back(
"-mllvm");
1315 CmdArgs.push_back(
"-asan-max-inline-poisoning-size=0");
1316 CmdArgs.push_back(
"-mllvm");
1317 CmdArgs.push_back(
"-asan-guard-against-version-mismatch=0");
1322 if (AsanDtorKind != llvm::AsanDtorKind::Invalid) {
1323 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-address-destructor=" +
1327 if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
1328 CmdArgs.push_back(Args.MakeArgString(
1329 "-fsanitize-address-use-after-return=" +
1333 if (!HwasanAbi.empty()) {
1334 CmdArgs.push_back(
"-default-function-attr");
1335 CmdArgs.push_back(Args.MakeArgString(
"hwasan-abi=" + HwasanAbi));
1338 if (Sanitizers.
has(SanitizerKind::HWAddress) && !HwasanUseAliases) {
1339 CmdArgs.push_back(
"-target-feature");
1340 CmdArgs.push_back(
"+tagged-globals");
1348 if (Sanitizers.
has(SanitizerKind::Memory) ||
1349 Sanitizers.
has(SanitizerKind::Address))
1350 CmdArgs.push_back(
"-fno-assume-sane-operator-new");
1357 if (Sanitizers.
has(SanitizerKind::FuzzerNoLink)) {
1358 CmdArgs.push_back(
"-fno-builtin-bcmp");
1359 CmdArgs.push_back(
"-fno-builtin-memcmp");
1360 CmdArgs.push_back(
"-fno-builtin-strncmp");
1361 CmdArgs.push_back(
"-fno-builtin-strcmp");
1362 CmdArgs.push_back(
"-fno-builtin-strncasecmp");
1363 CmdArgs.push_back(
"-fno-builtin-strcasecmp");
1364 CmdArgs.push_back(
"-fno-builtin-strstr");
1365 CmdArgs.push_back(
"-fno-builtin-strcasestr");
1366 CmdArgs.push_back(
"-fno-builtin-memmem");
1372 !Args.hasArg(options::OPT_fvisibility_EQ)) {
1373 TC.
getDriver().
Diag(clang::diag::err_drv_argument_only_allowed_with)
1379 if (Sanitizers.
has(SanitizerKind::MemtagStack) &&
1381 TC.
getDriver().
Diag(diag::err_stack_tagging_requires_hardware_feature);
1385 bool DiagnoseErrors) {
1386 assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
1387 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
1388 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
1389 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
1390 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
1391 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) &&
1392 "Invalid argument in parseArgValues!");
1394 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1395 const char *
Value = A->getValue(i);
1398 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
1399 0 == strcmp(
"all",
Value))
1406 else if (DiagnoseErrors)
1407 D.
Diag(clang::diag::err_drv_unsupported_option_argument)
1408 << A->getSpelling() <<
Value;
1414 bool DiagnoseErrors) {
1415 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
1416 A->getOption().matches(options::OPT_fno_sanitize_coverage));
1418 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1419 const char *
Value = A->getValue(i);
1420 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;
1450 bool DiagnoseErrors) {
1452 A->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ) ||
1453 A->getOption().matches(
1454 options::OPT_fno_experimental_sanitize_metadata_EQ));
1456 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1457 const char *
Value = A->getValue(i);
1458 int F = llvm::StringSwitch<int>(
Value)
1464 if (F == 0 && DiagnoseErrors)
1465 D.
Diag(clang::diag::err_drv_unsupported_option_argument)
1466 << A->getSpelling() <<
Value;
1474 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
1477 const auto *Arg = *I;
1478 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
1481 if (AddKinds & Mask)
1483 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
1486 Mask &= ~RemoveKinds;
1489 llvm_unreachable(
"arg list didn't provide expected value");
1493 assert(A->getOption().matches(options::OPT_fsanitize_EQ) &&
1494 "Invalid argument in describeSanitizerArg!");
1496 std::string Sanitizers;
1497 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1501 if (!Sanitizers.empty())
1503 Sanitizers += A->getValue(i);
1507 assert(!Sanitizers.empty() &&
"arg didn't provide expected value");
1508 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 isExecuteOnlyTarget(const llvm::Triple &Triple, const llvm::opt::ArgList &Args)
Return true if an execute-only target disallows data access to code sections.
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 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 ...
static const SanitizerMask NotAllowedWithExecuteOnly
@ 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).
The JSON file list parser is used to communicate input to InstallAPI.
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.