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) <<
true
801 <<
"-fsanitize-coverage=trace-pc-guard";
812 CoverageFeatures = 0;
814 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
816 CoverageFeatures &= ~parseCoverageFeatures(D, Arg, DiagnoseErrors);
820 if (DiagnoseErrors) {
822 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
823 <<
"-fsanitize-coverage=func"
824 <<
"-fsanitize-coverage=bb";
826 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
827 <<
"-fsanitize-coverage=func"
828 <<
"-fsanitize-coverage=edge";
830 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
831 <<
"-fsanitize-coverage=bb"
832 <<
"-fsanitize-coverage=edge";
836 D.
Diag(clang::diag::warn_drv_deprecated_arg)
837 <<
"-fsanitize-coverage=trace-bb" <<
true
838 <<
"-fsanitize-coverage=trace-pc-guard";
840 D.
Diag(clang::diag::warn_drv_deprecated_arg)
841 <<
"-fsanitize-coverage=8bit-counters" <<
true
842 <<
"-fsanitize-coverage=trace-pc-guard";
850 if ((CoverageFeatures & InsertionPointTypes) &&
851 !(CoverageFeatures & InstrumentationTypes) && DiagnoseErrors) {
852 D.
Diag(clang::diag::warn_drv_deprecated_arg)
853 <<
"-fsanitize-coverage=[func|bb|edge]" <<
true
854 <<
"-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc],["
859 if (!(CoverageFeatures & InsertionPointTypes)) {
860 if (CoverageFeatures &
873 if (CoverageFeatures) {
875 D, Args, CoverageAllowlistFiles,
876 options::OPT_fsanitize_coverage_allowlist, OptSpecifier(),
877 clang::diag::err_drv_malformed_sanitizer_coverage_allowlist,
880 D, Args, CoverageIgnorelistFiles,
881 options::OPT_fsanitize_coverage_ignorelist, OptSpecifier(),
882 clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist,
887 for (
const auto *Arg :
888 Args.filtered(options::OPT_fexperimental_sanitize_metadata_EQ,
889 options::OPT_fno_experimental_sanitize_metadata_EQ)) {
890 if (Arg->getOption().matches(
891 options::OPT_fexperimental_sanitize_metadata_EQ)) {
893 BinaryMetadataFeatures |=
897 BinaryMetadataFeatures &=
898 ~parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);
903 if (BinaryMetadataFeatures) {
905 D, Args, BinaryMetadataIgnorelistFiles,
906 options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ,
908 clang::diag::err_drv_malformed_sanitizer_metadata_ignorelist,
913 Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan,
917 ImplicitCfiRuntime = TC.
getTriple().isAndroid();
919 if (AllAddedKinds & SanitizerKind::Address) {
922 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
923 StringRef S = A->getValue();
925 if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
926 AsanFieldPadding > 2) &&
928 D.
Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
932 if (Arg *WindowsDebugRTArg =
933 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
934 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
935 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
936 switch (WindowsDebugRTArg->getOption().getID()) {
937 case options::OPT__SLASH_MTd:
938 case options::OPT__SLASH_MDd:
939 case options::OPT__SLASH_LDd:
940 if (DiagnoseErrors) {
941 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
942 << WindowsDebugRTArg->getAsString(Args)
944 D.
Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
949 StableABI = Args.hasFlag(options::OPT_fsanitize_stable_abi,
950 options::OPT_fno_sanitize_stable_abi,
false);
952 AsanUseAfterScope = Args.hasFlag(
953 options::OPT_fsanitize_address_use_after_scope,
954 options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);
956 AsanPoisonCustomArrayCookie = Args.hasFlag(
957 options::OPT_fsanitize_address_poison_custom_array_cookie,
958 options::OPT_fno_sanitize_address_poison_custom_array_cookie,
959 AsanPoisonCustomArrayCookie);
961 AsanOutlineInstrumentation =
962 Args.hasFlag(options::OPT_fsanitize_address_outline_instrumentation,
963 options::OPT_fno_sanitize_address_outline_instrumentation,
964 AsanOutlineInstrumentation);
966 AsanGlobalsDeadStripping = Args.hasFlag(
967 options::OPT_fsanitize_address_globals_dead_stripping,
968 options::OPT_fno_sanitize_address_globals_dead_stripping,
true);
974 AsanUseOdrIndicator =
975 Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
976 options::OPT_fno_sanitize_address_use_odr_indicator,
979 if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) {
980 AsanInvalidPointerCmp =
true;
983 if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) {
984 AsanInvalidPointerSub =
true;
988 (Args.hasArg(options::OPT_mkernel) ||
989 Args.hasArg(options::OPT_fapple_kext))) {
990 AsanDtorKind = llvm::AsanDtorKind::None;
993 if (
const auto *Arg =
994 Args.getLastArg(options::OPT_sanitize_address_destructor_EQ)) {
996 if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid && DiagnoseErrors) {
997 TC.
getDriver().
Diag(clang::diag::err_drv_unsupported_option_argument)
998 << Arg->getSpelling() << Arg->getValue();
1000 AsanDtorKind = parsedAsanDtorKind;
1003 if (
const auto *Arg = Args.getLastArg(
1004 options::OPT_sanitize_address_use_after_return_EQ)) {
1005 auto parsedAsanUseAfterReturn =
1007 if (parsedAsanUseAfterReturn ==
1008 llvm::AsanDetectStackUseAfterReturnMode::Invalid &&
1010 TC.
getDriver().
Diag(clang::diag::err_drv_unsupported_option_argument)
1011 << Arg->getSpelling() << Arg->getValue();
1013 AsanUseAfterReturn = parsedAsanUseAfterReturn;
1017 AsanUseAfterScope =
false;
1020 SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract;
1021 if ((AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) &&
1023 TC.
getDriver().
Diag(clang::diag::err_drv_argument_only_allowed_with)
1025 SanitizerKind::PointerCompare |
1026 SanitizerKind::PointerSubtract)
1027 <<
"-fsanitize=address";
1031 if (AllAddedKinds & SanitizerKind::HWAddress) {
1032 if (Arg *HwasanAbiArg =
1033 Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {
1034 HwasanAbi = HwasanAbiArg->getValue();
1035 if (HwasanAbi !=
"platform" && HwasanAbi !=
"interceptor" &&
1037 D.
Diag(clang::diag::err_drv_invalid_value)
1038 << HwasanAbiArg->getAsString(Args) << HwasanAbi;
1040 HwasanAbi =
"interceptor";
1042 if (TC.
getTriple().getArch() == llvm::Triple::x86_64)
1043 HwasanUseAliases = Args.hasFlag(
1044 options::OPT_fsanitize_hwaddress_experimental_aliasing,
1045 options::OPT_fno_sanitize_hwaddress_experimental_aliasing,
1049 if (AllAddedKinds & SanitizerKind::SafeStack) {
1056 Args.hasFlag(options::OPT_fsanitize_link_runtime,
1057 options::OPT_fno_sanitize_link_runtime, LinkRuntimes);
1060 LinkCXXRuntimes = Args.hasArg(options::OPT_fsanitize_link_cxx_runtime,
1061 options::OPT_fno_sanitize_link_cxx_runtime,
1065 NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile,
1066 options::OPT_fmemory_profile_EQ,
1067 options::OPT_fno_memory_profile,
false);
1070 Sanitizers.
Mask |= Kinds;
1071 RecoverableSanitizers.
Mask |= RecoverableKinds;
1072 TrapSanitizers.
Mask |= TrappingKinds;
1073 assert(!(RecoverableKinds & TrappingKinds) &&
1074 "Overlap between recoverable and trapping sanitizers");
1079#define SANITIZER(NAME, ID) \
1080 if (Sanitizers.has(SanitizerKind::ID)) { \
1085#include "clang/Basic/Sanitizers.def"
1090 llvm::opt::ArgStringList &CmdArgs,
1091 const char *SCLOptFlag,
1092 const std::vector<std::string> &SCLFiles) {
1093 for (
const auto &SCLPath : SCLFiles) {
1096 CmdArgs.push_back(Args.MakeArgString(SCLOpt));
1101 const llvm::opt::ArgList &Args,
1102 llvm::opt::ArgStringList &CmdArgs,
1103 StringRef SymbolName) {
1105 LinkerOptionFlag =
"--linker-option=/include:";
1106 if (TC.
getTriple().getArch() == llvm::Triple::x86) {
1108 LinkerOptionFlag +=
'_';
1110 LinkerOptionFlag += SymbolName;
1111 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
1115 for (
auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End;
1117 auto It = std::find(Start, End, StringRef(
"+mte"));
1120 if (It > Start && *std::prev(It) == StringRef(
"-target-feature"))
1128 llvm::opt::ArgStringList &CmdArgs,
1136 bool GPUSanitize =
false;
1138 if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
1147 std::pair<int, const char *> CoverageFlags[] = {
1148 std::make_pair(
CoverageFunc,
"-fsanitize-coverage-type=1"),
1149 std::make_pair(
CoverageBB,
"-fsanitize-coverage-type=2"),
1150 std::make_pair(
CoverageEdge,
"-fsanitize-coverage-type=3"),
1159 "-fsanitize-coverage-trace-pc-guard"),
1161 "-fsanitize-coverage-inline-8bit-counters"),
1163 "-fsanitize-coverage-inline-bool-flag"),
1170 for (
auto F : CoverageFlags) {
1171 if (CoverageFeatures & F.first)
1172 CmdArgs.push_back(F.second);
1175 Args, CmdArgs,
"-fsanitize-coverage-allowlist=", CoverageAllowlistFiles);
1177 CoverageIgnorelistFiles);
1182 const std::pair<int, std::string> BinaryMetadataFlags[] = {
1186 for (
const auto &F : BinaryMetadataFlags) {
1187 if (BinaryMetadataFeatures & F.first)
1189 Args.MakeArgString(
"-fexperimental-sanitize-metadata=" + F.second));
1192 "-fexperimental-sanitize-metadata-ignorelist=",
1193 BinaryMetadataIgnorelistFiles);
1197 Args.hasFlag(options::OPT_frtlib_defaultlib,
1198 options::OPT_fno_rtlib_defaultlib,
true)) {
1202 Args.MakeArgString(
"--dependent-lib=" +
1205 CmdArgs.push_back(Args.MakeArgString(
1206 "--dependent-lib=" +
1210 Args.hasFlag(options::OPT_frtlib_defaultlib,
1211 options::OPT_fno_rtlib_defaultlib,
true)) {
1212 CmdArgs.push_back(Args.MakeArgString(
1219 CmdArgs.push_back(Args.MakeArgString(
1224 if (Sanitizers.
empty())
1226 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize=" +
toString(Sanitizers)));
1228 if (!RecoverableSanitizers.
empty())
1229 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-recover=" +
1232 if (!TrapSanitizers.
empty())
1234 Args.MakeArgString(
"-fsanitize-trap=" +
toString(TrapSanitizers)));
1237 "-fsanitize-ignorelist=", UserIgnorelistFiles);
1239 "-fsanitize-system-ignorelist=", SystemIgnorelistFiles);
1241 if (MsanTrackOrigins)
1242 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-memory-track-origins=" +
1243 Twine(MsanTrackOrigins)));
1245 if (MsanUseAfterDtor)
1246 CmdArgs.push_back(
"-fsanitize-memory-use-after-dtor");
1248 if (!MsanParamRetval)
1249 CmdArgs.push_back(
"-fno-sanitize-memory-param-retval");
1252 if (!TsanMemoryAccess) {
1253 CmdArgs.push_back(
"-mllvm");
1254 CmdArgs.push_back(
"-tsan-instrument-memory-accesses=0");
1255 CmdArgs.push_back(
"-mllvm");
1256 CmdArgs.push_back(
"-tsan-instrument-memintrinsics=0");
1258 if (!TsanFuncEntryExit) {
1259 CmdArgs.push_back(
"-mllvm");
1260 CmdArgs.push_back(
"-tsan-instrument-func-entry-exit=0");
1263 CmdArgs.push_back(
"-mllvm");
1264 CmdArgs.push_back(
"-tsan-instrument-atomics=0");
1267 if (HwasanUseAliases) {
1268 CmdArgs.push_back(
"-mllvm");
1269 CmdArgs.push_back(
"-hwasan-experimental-use-page-aliases=1");
1273 CmdArgs.push_back(
"-fsanitize-cfi-cross-dso");
1275 if (CfiICallGeneralizePointers)
1276 CmdArgs.push_back(
"-fsanitize-cfi-icall-generalize-pointers");
1278 if (CfiICallNormalizeIntegers)
1279 CmdArgs.push_back(
"-fsanitize-cfi-icall-experimental-normalize-integers");
1281 if (CfiCanonicalJumpTables)
1282 CmdArgs.push_back(
"-fsanitize-cfi-canonical-jump-tables");
1285 CmdArgs.push_back(
"-fsanitize-stats");
1288 CmdArgs.push_back(
"-fsanitize-minimal-runtime");
1290 if (AsanFieldPadding)
1291 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-address-field-padding=" +
1292 Twine(AsanFieldPadding)));
1294 if (AsanUseAfterScope)
1295 CmdArgs.push_back(
"-fsanitize-address-use-after-scope");
1297 if (AsanPoisonCustomArrayCookie)
1298 CmdArgs.push_back(
"-fsanitize-address-poison-custom-array-cookie");
1300 if (AsanGlobalsDeadStripping)
1301 CmdArgs.push_back(
"-fsanitize-address-globals-dead-stripping");
1303 if (!AsanUseOdrIndicator)
1304 CmdArgs.push_back(
"-fno-sanitize-address-use-odr-indicator");
1306 if (AsanInvalidPointerCmp) {
1307 CmdArgs.push_back(
"-mllvm");
1308 CmdArgs.push_back(
"-asan-detect-invalid-pointer-cmp");
1311 if (AsanInvalidPointerSub) {
1312 CmdArgs.push_back(
"-mllvm");
1313 CmdArgs.push_back(
"-asan-detect-invalid-pointer-sub");
1316 if (AsanOutlineInstrumentation) {
1317 CmdArgs.push_back(
"-mllvm");
1318 CmdArgs.push_back(
"-asan-instrumentation-with-call-threshold=0");
1325 CmdArgs.push_back(
"-mllvm");
1326 CmdArgs.push_back(
"-asan-instrumentation-with-call-threshold=0");
1327 CmdArgs.push_back(
"-mllvm");
1328 CmdArgs.push_back(
"-asan-max-inline-poisoning-size=0");
1329 CmdArgs.push_back(
"-mllvm");
1330 CmdArgs.push_back(
"-asan-guard-against-version-mismatch=0");
1335 if (AsanDtorKind != llvm::AsanDtorKind::Invalid) {
1336 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-address-destructor=" +
1340 if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
1341 CmdArgs.push_back(Args.MakeArgString(
1342 "-fsanitize-address-use-after-return=" +
1346 if (!HwasanAbi.empty()) {
1347 CmdArgs.push_back(
"-default-function-attr");
1348 CmdArgs.push_back(Args.MakeArgString(
"hwasan-abi=" + HwasanAbi));
1351 if (Sanitizers.
has(SanitizerKind::HWAddress) && !HwasanUseAliases) {
1352 CmdArgs.push_back(
"-target-feature");
1353 CmdArgs.push_back(
"+tagged-globals");
1361 if (Sanitizers.
has(SanitizerKind::Memory) ||
1362 Sanitizers.
has(SanitizerKind::Address))
1363 CmdArgs.push_back(
"-fno-assume-sane-operator-new");
1370 if (Sanitizers.
has(SanitizerKind::FuzzerNoLink)) {
1371 CmdArgs.push_back(
"-fno-builtin-bcmp");
1372 CmdArgs.push_back(
"-fno-builtin-memcmp");
1373 CmdArgs.push_back(
"-fno-builtin-strncmp");
1374 CmdArgs.push_back(
"-fno-builtin-strcmp");
1375 CmdArgs.push_back(
"-fno-builtin-strncasecmp");
1376 CmdArgs.push_back(
"-fno-builtin-strcasecmp");
1377 CmdArgs.push_back(
"-fno-builtin-strstr");
1378 CmdArgs.push_back(
"-fno-builtin-strcasestr");
1379 CmdArgs.push_back(
"-fno-builtin-memmem");
1385 !Args.hasArg(options::OPT_fvisibility_EQ)) {
1386 TC.
getDriver().
Diag(clang::diag::err_drv_argument_only_allowed_with)
1392 if (Sanitizers.
has(SanitizerKind::MemtagStack) &&
1394 TC.
getDriver().
Diag(diag::err_stack_tagging_requires_hardware_feature);
1398 bool DiagnoseErrors) {
1399 assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
1400 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
1401 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
1402 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
1403 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
1404 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) &&
1405 "Invalid argument in parseArgValues!");
1407 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1408 const char *
Value = A->getValue(i);
1411 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
1412 0 == strcmp(
"all",
Value))
1419 else if (DiagnoseErrors)
1420 D.
Diag(clang::diag::err_drv_unsupported_option_argument)
1421 << A->getSpelling() <<
Value;
1427 bool DiagnoseErrors) {
1428 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
1429 A->getOption().matches(options::OPT_fno_sanitize_coverage));
1431 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1432 const char *
Value = A->getValue(i);
1433 int F = llvm::StringSwitch<int>(
Value)
1454 if (F == 0 && DiagnoseErrors)
1455 D.
Diag(clang::diag::err_drv_unsupported_option_argument)
1456 << A->getSpelling() <<
Value;
1463 bool DiagnoseErrors) {
1465 A->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ) ||
1466 A->getOption().matches(
1467 options::OPT_fno_experimental_sanitize_metadata_EQ));
1469 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1470 const char *
Value = A->getValue(i);
1471 int F = llvm::StringSwitch<int>(
Value)
1477 if (F == 0 && DiagnoseErrors)
1478 D.
Diag(clang::diag::err_drv_unsupported_option_argument)
1479 << A->getSpelling() <<
Value;
1487 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
1490 const auto *Arg = *I;
1491 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
1494 if (AddKinds & Mask)
1496 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
1499 Mask &= ~RemoveKinds;
1502 llvm_unreachable(
"arg list didn't provide expected value");
1506 assert(A->getOption().matches(options::OPT_fsanitize_EQ) &&
1507 "Invalid argument in describeSanitizerArg!");
1509 std::string Sanitizers;
1510 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1514 if (!Sanitizers.empty())
1516 Sanitizers += A->getValue(i);
1520 assert(!Sanitizers.empty() &&
"arg didn't provide expected value");
1521 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.