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::UndefinedGroup) {
493 bool S = Args.hasFlagNoClaim(options::OPT_fno_strict_overflow,
494 options::OPT_fstrict_overflow,
false);
495 if (Args.hasFlagNoClaim(options::OPT_fwrapv, options::OPT_fno_wrapv, S))
500 if (Add & SanitizerKind::Fuzzer)
501 Add |= SanitizerKind::FuzzerNoLink;
504 if (Add & SanitizerKind::FuzzerNoLink) {
513 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
520 std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
521 std::make_pair(SanitizerKind::Address,
522 SanitizerKind::Thread | SanitizerKind::Memory),
523 std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory),
524 std::make_pair(SanitizerKind::Leak,
525 SanitizerKind::Thread | SanitizerKind::Memory),
526 std::make_pair(SanitizerKind::KernelAddress,
527 SanitizerKind::Address | SanitizerKind::Leak |
528 SanitizerKind::Thread | SanitizerKind::Memory),
529 std::make_pair(SanitizerKind::HWAddress,
530 SanitizerKind::Address | SanitizerKind::Thread |
531 SanitizerKind::Memory | SanitizerKind::KernelAddress),
532 std::make_pair(SanitizerKind::Scudo,
533 SanitizerKind::Address | SanitizerKind::HWAddress |
534 SanitizerKind::Leak | SanitizerKind::Thread |
535 SanitizerKind::Memory | SanitizerKind::KernelAddress),
536 std::make_pair(SanitizerKind::SafeStack,
538 : SanitizerKind::Leak) |
539 SanitizerKind::Address | SanitizerKind::HWAddress |
540 SanitizerKind::Thread | SanitizerKind::Memory |
541 SanitizerKind::KernelAddress),
542 std::make_pair(SanitizerKind::KernelHWAddress,
543 SanitizerKind::Address | SanitizerKind::HWAddress |
544 SanitizerKind::Leak | SanitizerKind::Thread |
545 SanitizerKind::Memory | SanitizerKind::KernelAddress |
546 SanitizerKind::SafeStack),
547 std::make_pair(SanitizerKind::KernelMemory,
548 SanitizerKind::Address | SanitizerKind::HWAddress |
549 SanitizerKind::Leak | SanitizerKind::Thread |
550 SanitizerKind::Memory | SanitizerKind::KernelAddress |
551 SanitizerKind::Scudo | SanitizerKind::SafeStack),
552 std::make_pair(SanitizerKind::MemTag,
553 SanitizerKind::Address | SanitizerKind::KernelAddress |
554 SanitizerKind::HWAddress |
555 SanitizerKind::KernelHWAddress),
556 std::make_pair(SanitizerKind::KCFI, SanitizerKind::Function)};
562 for (
auto G : IncompatibleGroups) {
564 if ((
Default & Group) && (Kinds & G.second))
578 D.
Diag(diag::err_drv_argument_only_allowed_with)
582 if ((Kinds & SanitizerKind::ShadowCallStack) && TC.
getTriple().isAArch64() &&
583 !llvm::AArch64::isX18ReservedByDefault(TC.
getTriple()) &&
584 !Args.hasArg(options::OPT_ffixed_x18) && DiagnoseErrors) {
585 D.
Diag(diag::err_drv_argument_only_allowed_with)
594 if (~Supported & SanitizerKind::Vptr) {
600 if (KindsToDiagnose) {
602 S.Mask = KindsToDiagnose;
604 D.
Diag(diag::err_drv_unsupported_opt_for_target)
606 Kinds &= ~KindsToDiagnose;
611 for (
auto G : IncompatibleGroups) {
616 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
619 Kinds &= ~Incompatible;
632 for (
const auto *Arg : Args) {
633 if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
640 SetToDiagnose.
Mask |= KindsToDiagnose;
642 D.
Diag(diag::err_drv_unsupported_option_argument)
643 << Arg->getSpelling() <<
toString(SetToDiagnose);
644 DiagnosedUnrecoverableKinds |= KindsToDiagnose;
648 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {
655 SetToDiagnose.
Mask |= KindsToDiagnose;
657 D.
Diag(diag::err_drv_unsupported_option_argument)
658 << Arg->getSpelling() <<
toString(SetToDiagnose);
659 DiagnosedAlwaysRecoverableKinds |= KindsToDiagnose;
661 RecoverableKinds &= ~expandSanitizerGroups(Remove);
665 RecoverableKinds &= Kinds;
666 RecoverableKinds &= ~Unrecoverable;
668 TrappingKinds &= Kinds;
669 RecoverableKinds &= ~TrappingKinds;
674 if (!Args.hasArgNoClaim(options::OPT_fno_sanitize_ignorelist))
680 D, Args, UserIgnorelistFiles, options::OPT_fsanitize_ignorelist_EQ,
681 options::OPT_fno_sanitize_ignorelist,
682 clang::diag::err_drv_malformed_sanitizer_ignorelist, DiagnoseErrors);
685 if (AllAddedKinds & SanitizerKind::Memory) {
687 Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
688 options::OPT_fno_sanitize_memory_track_origins)) {
689 if (!A->getOption().matches(
690 options::OPT_fno_sanitize_memory_track_origins)) {
691 StringRef S = A->getValue();
692 if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
693 MsanTrackOrigins > 2) {
695 D.
Diag(clang::diag::err_drv_invalid_value)
696 << A->getAsString(Args) << S;
700 MsanUseAfterDtor = Args.hasFlag(
701 options::OPT_fsanitize_memory_use_after_dtor,
702 options::OPT_fno_sanitize_memory_use_after_dtor, MsanUseAfterDtor);
703 MsanParamRetval = Args.hasFlag(
704 options::OPT_fsanitize_memory_param_retval,
705 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
706 }
else if (AllAddedKinds & SanitizerKind::KernelMemory) {
707 MsanUseAfterDtor =
false;
708 MsanParamRetval = Args.hasFlag(
709 options::OPT_fsanitize_memory_param_retval,
710 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
712 MsanUseAfterDtor =
false;
713 MsanParamRetval =
false;
716 if (AllAddedKinds & SanitizerKind::MemTag) {
718 Args.getLastArgValue(options::OPT_fsanitize_memtag_mode_EQ,
"sync");
719 if (S ==
"async" || S ==
"sync") {
720 MemtagMode = S.str();
722 D.
Diag(clang::diag::err_drv_invalid_value_with_suggestion)
723 <<
"-fsanitize-memtag-mode=" << S <<
"{async, sync}";
728 if (AllAddedKinds & SanitizerKind::Thread) {
729 TsanMemoryAccess = Args.hasFlag(
730 options::OPT_fsanitize_thread_memory_access,
731 options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess);
732 TsanFuncEntryExit = Args.hasFlag(
733 options::OPT_fsanitize_thread_func_entry_exit,
734 options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit);
736 Args.hasFlag(options::OPT_fsanitize_thread_atomics,
737 options::OPT_fno_sanitize_thread_atomics, TsanAtomics);
740 if (AllAddedKinds & SanitizerKind::CFI) {
743 NeedPIE |= CfiCrossDso;
744 CfiICallGeneralizePointers =
745 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
747 CfiICallNormalizeIntegers =
748 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
750 if (CfiCrossDso && CfiICallGeneralizePointers && DiagnoseErrors)
751 D.
Diag(diag::err_drv_argument_not_allowed_with)
752 <<
"-fsanitize-cfi-cross-dso"
753 <<
"-fsanitize-cfi-icall-generalize-pointers";
755 CfiCanonicalJumpTables =
756 Args.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables,
757 options::OPT_fno_sanitize_cfi_canonical_jump_tables,
true);
760 if (AllAddedKinds & SanitizerKind::KCFI) {
761 CfiICallNormalizeIntegers =
762 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
764 if (AllAddedKinds & SanitizerKind::CFI && DiagnoseErrors)
765 D.
Diag(diag::err_drv_argument_not_allowed_with)
770 Stats = Args.hasFlag(options::OPT_fsanitize_stats,
771 options::OPT_fno_sanitize_stats,
false);
773 if (MinimalRuntime) {
776 if (IncompatibleMask && DiagnoseErrors)
777 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
778 <<
"-fsanitize-minimal-runtime"
781 SanitizerMask NonTrappingCfi = Kinds & SanitizerKind::CFI & ~TrappingKinds;
782 if (NonTrappingCfi && DiagnoseErrors)
783 D.
Diag(clang::diag::err_drv_argument_only_allowed_with)
784 <<
"fsanitize-minimal-runtime"
785 <<
"fsanitize-trap=cfi";
790 for (
const auto *Arg : Args) {
791 if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
792 int LegacySanitizeCoverage;
793 if (Arg->getNumValues() == 1 &&
794 !StringRef(Arg->getValue(0))
795 .getAsInteger(0, LegacySanitizeCoverage)) {
796 CoverageFeatures = 0;
798 if (LegacySanitizeCoverage != 0 && DiagnoseErrors) {
799 D.
Diag(diag::warn_drv_deprecated_arg)
800 << Arg->getAsString(Args) <<
"-fsanitize-coverage=trace-pc-guard";
811 CoverageFeatures = 0;
813 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
815 CoverageFeatures &= ~parseCoverageFeatures(D, Arg, DiagnoseErrors);
819 if (DiagnoseErrors) {
821 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
822 <<
"-fsanitize-coverage=func"
823 <<
"-fsanitize-coverage=bb";
825 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
826 <<
"-fsanitize-coverage=func"
827 <<
"-fsanitize-coverage=edge";
829 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
830 <<
"-fsanitize-coverage=bb"
831 <<
"-fsanitize-coverage=edge";
835 D.
Diag(clang::diag::warn_drv_deprecated_arg)
836 <<
"-fsanitize-coverage=trace-bb"
837 <<
"-fsanitize-coverage=trace-pc-guard";
839 D.
Diag(clang::diag::warn_drv_deprecated_arg)
840 <<
"-fsanitize-coverage=8bit-counters"
841 <<
"-fsanitize-coverage=trace-pc-guard";
849 if ((CoverageFeatures & InsertionPointTypes) &&
850 !(CoverageFeatures & InstrumentationTypes) && DiagnoseErrors) {
851 D.
Diag(clang::diag::warn_drv_deprecated_arg)
852 <<
"-fsanitize-coverage=[func|bb|edge]"
853 <<
"-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc],["
858 if (!(CoverageFeatures & InsertionPointTypes)) {
859 if (CoverageFeatures &
872 if (CoverageFeatures) {
874 D, Args, CoverageAllowlistFiles,
875 options::OPT_fsanitize_coverage_allowlist, OptSpecifier(),
876 clang::diag::err_drv_malformed_sanitizer_coverage_allowlist,
879 D, Args, CoverageIgnorelistFiles,
880 options::OPT_fsanitize_coverage_ignorelist, OptSpecifier(),
881 clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist,
886 for (
const auto *Arg :
887 Args.filtered(options::OPT_fexperimental_sanitize_metadata_EQ,
888 options::OPT_fno_experimental_sanitize_metadata_EQ)) {
889 if (Arg->getOption().matches(
890 options::OPT_fexperimental_sanitize_metadata_EQ)) {
892 BinaryMetadataFeatures |=
896 BinaryMetadataFeatures &=
897 ~parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);
902 if (BinaryMetadataFeatures) {
904 D, Args, BinaryMetadataIgnorelistFiles,
905 options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ,
907 clang::diag::err_drv_malformed_sanitizer_metadata_ignorelist,
912 Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan,
916 ImplicitCfiRuntime = TC.
getTriple().isAndroid();
918 if (AllAddedKinds & SanitizerKind::Address) {
921 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
922 StringRef S = A->getValue();
924 if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
925 AsanFieldPadding > 2) &&
927 D.
Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
931 if (Arg *WindowsDebugRTArg =
932 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
933 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
934 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
935 switch (WindowsDebugRTArg->getOption().getID()) {
936 case options::OPT__SLASH_MTd:
937 case options::OPT__SLASH_MDd:
938 case options::OPT__SLASH_LDd:
939 if (DiagnoseErrors) {
940 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
941 << WindowsDebugRTArg->getAsString(Args)
943 D.
Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
948 StableABI = Args.hasFlag(options::OPT_fsanitize_stable_abi,
949 options::OPT_fno_sanitize_stable_abi,
false);
951 AsanUseAfterScope = Args.hasFlag(
952 options::OPT_fsanitize_address_use_after_scope,
953 options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);
955 AsanPoisonCustomArrayCookie = Args.hasFlag(
956 options::OPT_fsanitize_address_poison_custom_array_cookie,
957 options::OPT_fno_sanitize_address_poison_custom_array_cookie,
958 AsanPoisonCustomArrayCookie);
960 AsanOutlineInstrumentation =
961 Args.hasFlag(options::OPT_fsanitize_address_outline_instrumentation,
962 options::OPT_fno_sanitize_address_outline_instrumentation,
963 AsanOutlineInstrumentation);
965 AsanGlobalsDeadStripping = Args.hasFlag(
966 options::OPT_fsanitize_address_globals_dead_stripping,
967 options::OPT_fno_sanitize_address_globals_dead_stripping,
true);
973 AsanUseOdrIndicator =
974 Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
975 options::OPT_fno_sanitize_address_use_odr_indicator,
978 if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) {
979 AsanInvalidPointerCmp =
true;
982 if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) {
983 AsanInvalidPointerSub =
true;
987 (Args.hasArg(options::OPT_mkernel) ||
988 Args.hasArg(options::OPT_fapple_kext))) {
989 AsanDtorKind = llvm::AsanDtorKind::None;
992 if (
const auto *Arg =
993 Args.getLastArg(options::OPT_sanitize_address_destructor_EQ)) {
995 if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid && DiagnoseErrors) {
996 TC.
getDriver().
Diag(clang::diag::err_drv_unsupported_option_argument)
997 << Arg->getSpelling() << Arg->getValue();
999 AsanDtorKind = parsedAsanDtorKind;
1002 if (
const auto *Arg = Args.getLastArg(
1003 options::OPT_sanitize_address_use_after_return_EQ)) {
1004 auto parsedAsanUseAfterReturn =
1006 if (parsedAsanUseAfterReturn ==
1007 llvm::AsanDetectStackUseAfterReturnMode::Invalid &&
1009 TC.
getDriver().
Diag(clang::diag::err_drv_unsupported_option_argument)
1010 << Arg->getSpelling() << Arg->getValue();
1012 AsanUseAfterReturn = parsedAsanUseAfterReturn;
1016 AsanUseAfterScope =
false;
1019 SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract;
1020 if ((AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) &&
1022 TC.
getDriver().
Diag(clang::diag::err_drv_argument_only_allowed_with)
1024 SanitizerKind::PointerCompare |
1025 SanitizerKind::PointerSubtract)
1026 <<
"-fsanitize=address";
1030 if (AllAddedKinds & SanitizerKind::HWAddress) {
1031 if (Arg *HwasanAbiArg =
1032 Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {
1033 HwasanAbi = HwasanAbiArg->getValue();
1034 if (HwasanAbi !=
"platform" && HwasanAbi !=
"interceptor" &&
1036 D.
Diag(clang::diag::err_drv_invalid_value)
1037 << HwasanAbiArg->getAsString(Args) << HwasanAbi;
1039 HwasanAbi =
"interceptor";
1041 if (TC.
getTriple().getArch() == llvm::Triple::x86_64)
1042 HwasanUseAliases = Args.hasFlag(
1043 options::OPT_fsanitize_hwaddress_experimental_aliasing,
1044 options::OPT_fno_sanitize_hwaddress_experimental_aliasing,
1048 if (AllAddedKinds & SanitizerKind::SafeStack) {
1055 Args.hasFlag(options::OPT_fsanitize_link_runtime,
1056 options::OPT_fno_sanitize_link_runtime, LinkRuntimes);
1059 LinkCXXRuntimes = Args.hasArg(options::OPT_fsanitize_link_cxx_runtime,
1060 options::OPT_fno_sanitize_link_cxx_runtime,
1064 NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile,
1065 options::OPT_fmemory_profile_EQ,
1066 options::OPT_fno_memory_profile,
false);
1069 Sanitizers.
Mask |= Kinds;
1070 RecoverableSanitizers.
Mask |= RecoverableKinds;
1071 TrapSanitizers.
Mask |= TrappingKinds;
1072 assert(!(RecoverableKinds & TrappingKinds) &&
1073 "Overlap between recoverable and trapping sanitizers");
1078#define SANITIZER(NAME, ID) \
1079 if (Sanitizers.has(SanitizerKind::ID)) { \
1084#include "clang/Basic/Sanitizers.def"
1089 llvm::opt::ArgStringList &CmdArgs,
1090 const char *SCLOptFlag,
1091 const std::vector<std::string> &SCLFiles) {
1092 for (
const auto &SCLPath : SCLFiles) {
1095 CmdArgs.push_back(Args.MakeArgString(SCLOpt));
1100 const llvm::opt::ArgList &Args,
1101 llvm::opt::ArgStringList &CmdArgs,
1102 StringRef SymbolName) {
1104 LinkerOptionFlag =
"--linker-option=/include:";
1105 if (TC.
getTriple().getArch() == llvm::Triple::x86) {
1107 LinkerOptionFlag +=
'_';
1109 LinkerOptionFlag += SymbolName;
1110 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
1114 for (
auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End;
1116 auto It = std::find(Start, End, StringRef(
"+mte"));
1119 if (It > Start && *std::prev(It) == StringRef(
"-target-feature"))
1127 llvm::opt::ArgStringList &CmdArgs,
1135 bool GPUSanitize =
false;
1137 if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
1146 std::pair<int, const char *> CoverageFlags[] = {
1147 std::make_pair(
CoverageFunc,
"-fsanitize-coverage-type=1"),
1148 std::make_pair(
CoverageBB,
"-fsanitize-coverage-type=2"),
1149 std::make_pair(
CoverageEdge,
"-fsanitize-coverage-type=3"),
1158 "-fsanitize-coverage-trace-pc-guard"),
1160 "-fsanitize-coverage-inline-8bit-counters"),
1162 "-fsanitize-coverage-inline-bool-flag"),
1169 for (
auto F : CoverageFlags) {
1170 if (CoverageFeatures & F.first)
1171 CmdArgs.push_back(F.second);
1174 Args, CmdArgs,
"-fsanitize-coverage-allowlist=", CoverageAllowlistFiles);
1176 CoverageIgnorelistFiles);
1181 const std::pair<int, std::string> BinaryMetadataFlags[] = {
1185 for (
const auto &F : BinaryMetadataFlags) {
1186 if (BinaryMetadataFeatures & F.first)
1188 Args.MakeArgString(
"-fexperimental-sanitize-metadata=" + F.second));
1191 "-fexperimental-sanitize-metadata-ignorelist=",
1192 BinaryMetadataIgnorelistFiles);
1196 Args.hasFlag(options::OPT_frtlib_defaultlib,
1197 options::OPT_fno_rtlib_defaultlib,
true)) {
1201 Args.MakeArgString(
"--dependent-lib=" +
1204 CmdArgs.push_back(Args.MakeArgString(
1205 "--dependent-lib=" +
1209 Args.hasFlag(options::OPT_frtlib_defaultlib,
1210 options::OPT_fno_rtlib_defaultlib,
true)) {
1211 CmdArgs.push_back(Args.MakeArgString(
1218 CmdArgs.push_back(Args.MakeArgString(
1223 if (Sanitizers.
empty())
1225 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize=" +
toString(Sanitizers)));
1227 if (!RecoverableSanitizers.
empty())
1228 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-recover=" +
1231 if (!TrapSanitizers.
empty())
1233 Args.MakeArgString(
"-fsanitize-trap=" +
toString(TrapSanitizers)));
1236 "-fsanitize-ignorelist=", UserIgnorelistFiles);
1238 "-fsanitize-system-ignorelist=", SystemIgnorelistFiles);
1240 if (MsanTrackOrigins)
1241 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-memory-track-origins=" +
1242 Twine(MsanTrackOrigins)));
1244 if (MsanUseAfterDtor)
1245 CmdArgs.push_back(
"-fsanitize-memory-use-after-dtor");
1247 if (!MsanParamRetval)
1248 CmdArgs.push_back(
"-fno-sanitize-memory-param-retval");
1251 if (!TsanMemoryAccess) {
1252 CmdArgs.push_back(
"-mllvm");
1253 CmdArgs.push_back(
"-tsan-instrument-memory-accesses=0");
1254 CmdArgs.push_back(
"-mllvm");
1255 CmdArgs.push_back(
"-tsan-instrument-memintrinsics=0");
1257 if (!TsanFuncEntryExit) {
1258 CmdArgs.push_back(
"-mllvm");
1259 CmdArgs.push_back(
"-tsan-instrument-func-entry-exit=0");
1262 CmdArgs.push_back(
"-mllvm");
1263 CmdArgs.push_back(
"-tsan-instrument-atomics=0");
1266 if (HwasanUseAliases) {
1267 CmdArgs.push_back(
"-mllvm");
1268 CmdArgs.push_back(
"-hwasan-experimental-use-page-aliases=1");
1272 CmdArgs.push_back(
"-fsanitize-cfi-cross-dso");
1274 if (CfiICallGeneralizePointers)
1275 CmdArgs.push_back(
"-fsanitize-cfi-icall-generalize-pointers");
1277 if (CfiICallNormalizeIntegers)
1278 CmdArgs.push_back(
"-fsanitize-cfi-icall-experimental-normalize-integers");
1280 if (CfiCanonicalJumpTables)
1281 CmdArgs.push_back(
"-fsanitize-cfi-canonical-jump-tables");
1284 CmdArgs.push_back(
"-fsanitize-stats");
1287 CmdArgs.push_back(
"-fsanitize-minimal-runtime");
1289 if (AsanFieldPadding)
1290 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-address-field-padding=" +
1291 Twine(AsanFieldPadding)));
1293 if (AsanUseAfterScope)
1294 CmdArgs.push_back(
"-fsanitize-address-use-after-scope");
1296 if (AsanPoisonCustomArrayCookie)
1297 CmdArgs.push_back(
"-fsanitize-address-poison-custom-array-cookie");
1299 if (AsanGlobalsDeadStripping)
1300 CmdArgs.push_back(
"-fsanitize-address-globals-dead-stripping");
1302 if (!AsanUseOdrIndicator)
1303 CmdArgs.push_back(
"-fno-sanitize-address-use-odr-indicator");
1305 if (AsanInvalidPointerCmp) {
1306 CmdArgs.push_back(
"-mllvm");
1307 CmdArgs.push_back(
"-asan-detect-invalid-pointer-cmp");
1310 if (AsanInvalidPointerSub) {
1311 CmdArgs.push_back(
"-mllvm");
1312 CmdArgs.push_back(
"-asan-detect-invalid-pointer-sub");
1315 if (AsanOutlineInstrumentation) {
1316 CmdArgs.push_back(
"-mllvm");
1317 CmdArgs.push_back(
"-asan-instrumentation-with-call-threshold=0");
1324 CmdArgs.push_back(
"-mllvm");
1325 CmdArgs.push_back(
"-asan-instrumentation-with-call-threshold=0");
1326 CmdArgs.push_back(
"-mllvm");
1327 CmdArgs.push_back(
"-asan-max-inline-poisoning-size=0");
1328 CmdArgs.push_back(
"-mllvm");
1329 CmdArgs.push_back(
"-asan-guard-against-version-mismatch=0");
1334 if (AsanDtorKind != llvm::AsanDtorKind::Invalid) {
1335 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-address-destructor=" +
1339 if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
1340 CmdArgs.push_back(Args.MakeArgString(
1341 "-fsanitize-address-use-after-return=" +
1345 if (!HwasanAbi.empty()) {
1346 CmdArgs.push_back(
"-default-function-attr");
1347 CmdArgs.push_back(Args.MakeArgString(
"hwasan-abi=" + HwasanAbi));
1350 if (Sanitizers.
has(SanitizerKind::HWAddress) && !HwasanUseAliases) {
1351 CmdArgs.push_back(
"-target-feature");
1352 CmdArgs.push_back(
"+tagged-globals");
1360 if (Sanitizers.
has(SanitizerKind::Memory) ||
1361 Sanitizers.
has(SanitizerKind::Address))
1362 CmdArgs.push_back(
"-fno-assume-sane-operator-new");
1369 if (Sanitizers.
has(SanitizerKind::FuzzerNoLink)) {
1370 CmdArgs.push_back(
"-fno-builtin-bcmp");
1371 CmdArgs.push_back(
"-fno-builtin-memcmp");
1372 CmdArgs.push_back(
"-fno-builtin-strncmp");
1373 CmdArgs.push_back(
"-fno-builtin-strcmp");
1374 CmdArgs.push_back(
"-fno-builtin-strncasecmp");
1375 CmdArgs.push_back(
"-fno-builtin-strcasecmp");
1376 CmdArgs.push_back(
"-fno-builtin-strstr");
1377 CmdArgs.push_back(
"-fno-builtin-strcasestr");
1378 CmdArgs.push_back(
"-fno-builtin-memmem");
1384 !Args.hasArg(options::OPT_fvisibility_EQ)) {
1385 TC.
getDriver().
Diag(clang::diag::err_drv_argument_only_allowed_with)
1391 if (Sanitizers.
has(SanitizerKind::MemtagStack) &&
1393 TC.
getDriver().
Diag(diag::err_stack_tagging_requires_hardware_feature);
1397 bool DiagnoseErrors) {
1398 assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
1399 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
1400 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
1401 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
1402 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
1403 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) &&
1404 "Invalid argument in parseArgValues!");
1406 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1407 const char *
Value = A->getValue(i);
1410 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
1411 0 == strcmp(
"all",
Value))
1418 else if (DiagnoseErrors)
1419 D.
Diag(clang::diag::err_drv_unsupported_option_argument)
1420 << A->getSpelling() <<
Value;
1426 bool DiagnoseErrors) {
1427 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
1428 A->getOption().matches(options::OPT_fno_sanitize_coverage));
1430 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1431 const char *
Value = A->getValue(i);
1432 int F = llvm::StringSwitch<int>(
Value)
1453 if (F == 0 && DiagnoseErrors)
1454 D.
Diag(clang::diag::err_drv_unsupported_option_argument)
1455 << A->getSpelling() <<
Value;
1462 bool DiagnoseErrors) {
1464 A->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ) ||
1465 A->getOption().matches(
1466 options::OPT_fno_experimental_sanitize_metadata_EQ));
1468 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1469 const char *
Value = A->getValue(i);
1470 int F = llvm::StringSwitch<int>(
Value)
1476 if (F == 0 && DiagnoseErrors)
1477 D.
Diag(clang::diag::err_drv_unsupported_option_argument)
1478 << A->getSpelling() <<
Value;
1486 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
1489 const auto *Arg = *I;
1490 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
1493 if (AddKinds & Mask)
1495 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
1498 Mask &= ~RemoveKinds;
1501 llvm_unreachable(
"arg list didn't provide expected value");
1505 assert(A->getOption().matches(options::OPT_fsanitize_EQ) &&
1506 "Invalid argument in describeSanitizerArg!");
1508 std::string Sanitizers;
1509 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1513 if (!Sanitizers.empty())
1515 Sanitizers += A->getValue(i);
1519 assert(!Sanitizers.empty() &&
"arg didn't provide expected value");
1520 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.