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 |
45 SanitizerKind::NumericalStability;
47 SanitizerKind::Address | SanitizerKind::HWAddress |
48 SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |
49 SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap |
50 SanitizerKind::MemtagGlobals | SanitizerKind::Memory |
51 SanitizerKind::KernelMemory | SanitizerKind::Leak |
52 SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::Bounds |
53 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
54 SanitizerKind::DataFlow | SanitizerKind::Fuzzer |
55 SanitizerKind::FuzzerNoLink | SanitizerKind::FloatDivideByZero |
56 SanitizerKind::SafeStack | SanitizerKind::ShadowCallStack |
57 SanitizerKind::Thread | SanitizerKind::ObjCCast | SanitizerKind::KCFI |
58 SanitizerKind::NumericalStability;
60 SanitizerKind::Undefined | SanitizerKind::Integer |
61 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
62 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;
64 SanitizerKind::Unreachable | SanitizerKind::Return;
66 SanitizerKind::KernelHWAddress |
70 (SanitizerKind::Undefined &
~SanitizerKind::Vptr) | SanitizerKind::Integer |
71 SanitizerKind::Nullability | SanitizerKind::LocalBounds |
72 SanitizerKind::CFI | SanitizerKind::FloatDivideByZero |
73 SanitizerKind::ObjCCast;
76 SanitizerKind::CFIVCall | SanitizerKind::CFINVCall |
77 SanitizerKind::CFIMFCall | SanitizerKind::CFIDerivedCast |
78 SanitizerKind::CFIUnrelatedCast;
81 SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap |
82 SanitizerKind::MemtagGlobals | SanitizerKind::KCFI;
115 bool DiagnoseErrors);
120 bool DiagnoseErrors);
125 bool DiagnoseErrors);
132 const llvm::opt::ArgList &Args,
149 const llvm::opt::ArgList &Args) {
152 return Args.hasFlagNoClaim(options::OPT_mexecute_only,
153 options::OPT_mno_execute_only,
false);
157 std::vector<std::string> &SCLFiles,
158 unsigned MalformedSCLErrorDiagID,
159 bool DiagnoseErrors) {
160 if (SCLFiles.empty())
164 std::unique_ptr<llvm::SpecialCaseList> SCL(
165 llvm::SpecialCaseList::create(SCLFiles,
D.getVFS(), BLError));
166 if (!SCL.get() && DiagnoseErrors)
167 D.Diag(MalformedSCLErrorDiagID) << BLError;
171 std::vector<std::string> &IgnorelistFiles,
172 bool DiagnoseErrors) {
176 } Ignorelists[] = {{
"asan_ignorelist.txt", SanitizerKind::Address},
177 {
"hwasan_ignorelist.txt", SanitizerKind::HWAddress},
178 {
"memtag_ignorelist.txt", SanitizerKind::MemTag},
179 {
"msan_ignorelist.txt", SanitizerKind::Memory},
180 {
"nsan_ignorelist.txt", SanitizerKind::NumericalStability},
181 {
"tsan_ignorelist.txt", SanitizerKind::Thread},
182 {
"dfsan_abilist.txt", SanitizerKind::DataFlow},
183 {
"cfi_ignorelist.txt", SanitizerKind::CFI},
184 {
"ubsan_ignorelist.txt",
185 SanitizerKind::Undefined | SanitizerKind::Integer |
186 SanitizerKind::Nullability |
187 SanitizerKind::FloatDivideByZero}};
189 for (
auto BL : Ignorelists) {
190 if (!(Kinds & BL.Mask))
194 llvm::sys::path::append(
Path,
"share", BL.File);
195 if (
D.getVFS().exists(
Path))
196 IgnorelistFiles.push_back(std::string(
Path));
197 else if (BL.Mask == SanitizerKind::CFI && DiagnoseErrors)
200 D.Diag(clang::diag::err_drv_missing_sanitizer_ignorelist) <<
Path;
203 D, IgnorelistFiles, clang::diag::err_drv_malformed_sanitizer_ignorelist,
210 const llvm::opt::ArgList &Args,
211 std::vector<std::string> &SCLFiles,
212 llvm::opt::OptSpecifier SCLOptionID,
213 llvm::opt::OptSpecifier NoSCLOptionID,
214 unsigned MalformedSCLErrorDiagID,
215 bool DiagnoseErrors) {
216 for (
const auto *Arg : Args) {
218 if (Arg->getOption().matches(SCLOptionID)) {
220 std::string SCLPath = Arg->getValue();
221 if (
D.getVFS().exists(SCLPath)) {
222 SCLFiles.push_back(SCLPath);
223 }
else if (DiagnoseErrors) {
224 D.Diag(clang::diag::err_drv_no_such_file) << SCLPath;
227 }
else if (Arg->getOption().matches(NoSCLOptionID)) {
239#define SANITIZER(NAME, ID)
240#define SANITIZER_GROUP(NAME, ID, ALIAS) \
241 if (Kinds & SanitizerKind::ID) \
242 Kinds |= SanitizerKind::ID##Group;
243#include "clang/Basic/Sanitizers.def"
248 const llvm::opt::ArgList &Args,
249 bool DiagnoseErrors) {
256 for (
const llvm::opt::Arg *Arg : llvm::reverse(Args)) {
257 if (Arg->getOption().matches(options::OPT_fsanitize_trap_EQ)) {
261 SanitizerMask InvalidValues = Add & ~TrappingSupportedWithGroups;
262 if (InvalidValues && DiagnoseErrors) {
264 S.Mask = InvalidValues;
265 D.Diag(diag::err_drv_unsupported_option_argument)
266 << Arg->getSpelling() <<
toString(S);
269 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) {
279 return TrappingKinds;
298 return !(Sanitizers.
Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
299 CfiCrossDso && !ImplicitCfiRuntime;
303 return (Sanitizers.
Mask & SanitizerKind::CFI & ~TrapSanitizers.
Mask) &&
304 CfiCrossDso && !ImplicitCfiRuntime;
318 const llvm::opt::ArgList &Args,
319 bool DiagnoseErrors) {
333 CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
334 options::OPT_fno_sanitize_cfi_cross_dso,
false);
343 Args.hasFlag(options::OPT_fsanitize_minimal_runtime,
344 options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime);
347 Arg *OptLevel = Args.getLastArg(options::OPT_O_Group);
348 bool RemoveObjectSizeAtO0 =
349 !OptLevel || OptLevel->getOption().matches(options::OPT_O0);
351 for (
const llvm::opt::Arg *Arg : llvm::reverse(Args)) {
352 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
356 if (RemoveObjectSizeAtO0) {
357 AllRemove |= SanitizerKind::ObjectSize;
361 if ((Add & SanitizerKind::ObjectSize) && DiagnoseErrors)
362 D.Diag(diag::warn_drv_object_size_disabled_O0)
363 << Arg->getAsString(Args);
374 Add & InvalidTrappingKinds & ~DiagnosedKinds) {
375 if (DiagnoseErrors) {
377 D.Diag(diag::err_drv_argument_not_allowed_with)
378 << Desc <<
"-fsanitize-trap=undefined";
380 DiagnosedKinds |= KindsToDiagnose;
382 Add &= ~InvalidTrappingKinds;
384 if (MinimalRuntime) {
387 if (DiagnoseErrors) {
389 D.Diag(diag::err_drv_argument_not_allowed_with)
390 << Desc <<
"-fsanitize-minimal-runtime";
392 DiagnosedKinds |= KindsToDiagnose;
394 Add &= ~NotAllowedWithMinimalRuntime;
397 if (llvm::opt::Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
398 StringRef CM = A->getValue();
400 (Add & SanitizerKind::Function & ~DiagnosedKinds)) {
402 D.Diag(diag::err_drv_argument_only_allowed_with)
403 <<
"-fsanitize=function"
406 DiagnosedKinds |= SanitizerKind::Function;
412 const llvm::Triple &Triple = TC.
getTriple();
416 if (DiagnoseErrors) {
418 D.Diag(diag::err_drv_argument_not_allowed_with)
419 << Desc << Triple.str();
421 DiagnosedKinds |= KindsToDiagnose;
423 Add &= ~NotAllowedWithExecuteOnly;
436 if (CfiCrossDso && (Add & SanitizerKind::CFIMFCall & ~DiagnosedKinds)) {
438 D.Diag(diag::err_drv_argument_not_allowed_with)
439 <<
"-fsanitize=cfi-mfcall"
440 <<
"-fsanitize-cfi-cross-dso";
442 DiagnosedKinds |= SanitizerKind::CFIMFCall;
445 if (
SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
446 if (DiagnoseErrors) {
448 D.Diag(diag::err_drv_unsupported_opt_for_target)
451 DiagnosedKinds |= KindsToDiagnose;
459 if (
const llvm::opt::Arg *NoRTTIArg = TC.
getRTTIArg()) {
460 assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) &&
461 "RTTI disabled without -fno-rtti option?");
465 D.Diag(diag::err_drv_argument_not_allowed_with)
466 <<
"-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
471 D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
475 AllRemove |= SanitizerKind::Vptr;
483 Add &= ~InvalidTrappingKinds;
484 if (MinimalRuntime) {
485 Add &= ~NotAllowedWithMinimalRuntime;
490 Add &= ~NotAllowedWithExecuteOnly;
495 if (Add & SanitizerKind::UndefinedGroup) {
496 bool S = Args.hasFlagNoClaim(options::OPT_fno_strict_overflow,
497 options::OPT_fstrict_overflow,
false);
498 if (Args.hasFlagNoClaim(options::OPT_fwrapv, options::OPT_fno_wrapv, S))
503 if (Add & SanitizerKind::Fuzzer)
504 Add |= SanitizerKind::FuzzerNoLink;
507 if (Add & SanitizerKind::FuzzerNoLink) {
516 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
523 std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
524 std::make_pair(SanitizerKind::Address,
525 SanitizerKind::Thread | SanitizerKind::Memory),
526 std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory),
527 std::make_pair(SanitizerKind::Leak,
528 SanitizerKind::Thread | SanitizerKind::Memory),
529 std::make_pair(SanitizerKind::KernelAddress,
530 SanitizerKind::Address | SanitizerKind::Leak |
531 SanitizerKind::Thread | SanitizerKind::Memory),
532 std::make_pair(SanitizerKind::HWAddress,
533 SanitizerKind::Address | SanitizerKind::Thread |
534 SanitizerKind::Memory | SanitizerKind::KernelAddress),
535 std::make_pair(SanitizerKind::Scudo,
536 SanitizerKind::Address | SanitizerKind::HWAddress |
537 SanitizerKind::Leak | SanitizerKind::Thread |
538 SanitizerKind::Memory | SanitizerKind::KernelAddress),
539 std::make_pair(SanitizerKind::SafeStack,
541 : SanitizerKind::Leak) |
542 SanitizerKind::Address | SanitizerKind::HWAddress |
543 SanitizerKind::Thread | SanitizerKind::Memory |
544 SanitizerKind::KernelAddress),
545 std::make_pair(SanitizerKind::KernelHWAddress,
546 SanitizerKind::Address | SanitizerKind::HWAddress |
547 SanitizerKind::Leak | SanitizerKind::Thread |
548 SanitizerKind::Memory | SanitizerKind::KernelAddress |
549 SanitizerKind::SafeStack),
550 std::make_pair(SanitizerKind::KernelMemory,
551 SanitizerKind::Address | SanitizerKind::HWAddress |
552 SanitizerKind::Leak | SanitizerKind::Thread |
553 SanitizerKind::Memory | SanitizerKind::KernelAddress |
554 SanitizerKind::Scudo | SanitizerKind::SafeStack),
555 std::make_pair(SanitizerKind::MemTag,
556 SanitizerKind::Address | SanitizerKind::KernelAddress |
557 SanitizerKind::HWAddress |
558 SanitizerKind::KernelHWAddress),
559 std::make_pair(SanitizerKind::KCFI, SanitizerKind::Function)};
565 for (
auto G : IncompatibleGroups) {
567 if ((
Default & Group) && (Kinds & G.second))
580 if ((Kinds &
NeedsLTO) && !
D.isUsingLTO() && DiagnoseErrors) {
581 D.Diag(diag::err_drv_argument_only_allowed_with)
585 if ((Kinds & SanitizerKind::ShadowCallStack) && TC.
getTriple().isAArch64() &&
586 !llvm::AArch64::isX18ReservedByDefault(TC.
getTriple()) &&
587 !Args.hasArg(options::OPT_ffixed_x18) && DiagnoseErrors) {
588 D.Diag(diag::err_drv_argument_only_allowed_with)
597 if (~Supported & SanitizerKind::Vptr) {
603 if (KindsToDiagnose) {
605 S.Mask = KindsToDiagnose;
607 D.Diag(diag::err_drv_unsupported_opt_for_target)
609 Kinds &= ~KindsToDiagnose;
614 for (
auto G : IncompatibleGroups) {
619 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
622 Kinds &= ~Incompatible;
635 for (
const auto *Arg : Args) {
636 if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
643 SetToDiagnose.
Mask |= KindsToDiagnose;
645 D.Diag(diag::err_drv_unsupported_option_argument)
646 << Arg->getSpelling() <<
toString(SetToDiagnose);
647 DiagnosedUnrecoverableKinds |= KindsToDiagnose;
651 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {
658 SetToDiagnose.
Mask |= KindsToDiagnose;
660 D.Diag(diag::err_drv_unsupported_option_argument)
661 << Arg->getSpelling() <<
toString(SetToDiagnose);
662 DiagnosedAlwaysRecoverableKinds |= KindsToDiagnose;
664 RecoverableKinds &= ~expandSanitizerGroups(Remove);
668 RecoverableKinds &= Kinds;
669 RecoverableKinds &= ~Unrecoverable;
671 TrappingKinds &= Kinds;
672 RecoverableKinds &= ~TrappingKinds;
677 if (!Args.hasArgNoClaim(options::OPT_fno_sanitize_ignorelist))
683 D, Args, UserIgnorelistFiles, options::OPT_fsanitize_ignorelist_EQ,
684 options::OPT_fno_sanitize_ignorelist,
685 clang::diag::err_drv_malformed_sanitizer_ignorelist, DiagnoseErrors);
688 if (AllAddedKinds & SanitizerKind::Memory) {
690 Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
691 options::OPT_fno_sanitize_memory_track_origins)) {
692 if (!A->getOption().matches(
693 options::OPT_fno_sanitize_memory_track_origins)) {
694 StringRef S = A->getValue();
695 if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
696 MsanTrackOrigins > 2) {
698 D.Diag(clang::diag::err_drv_invalid_value)
699 << A->getAsString(Args) << S;
703 MsanUseAfterDtor = Args.hasFlag(
704 options::OPT_fsanitize_memory_use_after_dtor,
705 options::OPT_fno_sanitize_memory_use_after_dtor, MsanUseAfterDtor);
706 MsanParamRetval = Args.hasFlag(
707 options::OPT_fsanitize_memory_param_retval,
708 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
709 }
else if (AllAddedKinds & SanitizerKind::KernelMemory) {
710 MsanUseAfterDtor =
false;
711 MsanParamRetval = Args.hasFlag(
712 options::OPT_fsanitize_memory_param_retval,
713 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
715 MsanUseAfterDtor =
false;
716 MsanParamRetval =
false;
719 if (AllAddedKinds & SanitizerKind::MemTag) {
721 Args.getLastArgValue(options::OPT_fsanitize_memtag_mode_EQ,
"sync");
722 if (S ==
"async" || S ==
"sync") {
723 MemtagMode = S.str();
725 D.Diag(clang::diag::err_drv_invalid_value_with_suggestion)
726 <<
"-fsanitize-memtag-mode=" << S <<
"{async, sync}";
731 if (AllAddedKinds & SanitizerKind::Thread) {
732 TsanMemoryAccess = Args.hasFlag(
733 options::OPT_fsanitize_thread_memory_access,
734 options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess);
735 TsanFuncEntryExit = Args.hasFlag(
736 options::OPT_fsanitize_thread_func_entry_exit,
737 options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit);
739 Args.hasFlag(options::OPT_fsanitize_thread_atomics,
740 options::OPT_fno_sanitize_thread_atomics, TsanAtomics);
743 if (AllAddedKinds & SanitizerKind::CFI) {
746 NeedPIE |= CfiCrossDso;
747 CfiICallGeneralizePointers =
748 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
750 CfiICallNormalizeIntegers =
751 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
753 if (CfiCrossDso && CfiICallGeneralizePointers && DiagnoseErrors)
754 D.Diag(diag::err_drv_argument_not_allowed_with)
755 <<
"-fsanitize-cfi-cross-dso"
756 <<
"-fsanitize-cfi-icall-generalize-pointers";
758 CfiCanonicalJumpTables =
759 Args.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables,
760 options::OPT_fno_sanitize_cfi_canonical_jump_tables,
true);
763 if (AllAddedKinds & SanitizerKind::KCFI) {
764 CfiICallNormalizeIntegers =
765 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
767 if (AllAddedKinds & SanitizerKind::CFI && DiagnoseErrors)
768 D.Diag(diag::err_drv_argument_not_allowed_with)
773 Stats = Args.hasFlag(options::OPT_fsanitize_stats,
774 options::OPT_fno_sanitize_stats,
false);
776 if (MinimalRuntime) {
779 if (IncompatibleMask && DiagnoseErrors)
780 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
781 <<
"-fsanitize-minimal-runtime"
784 SanitizerMask NonTrappingCfi = Kinds & SanitizerKind::CFI & ~TrappingKinds;
785 if (NonTrappingCfi && DiagnoseErrors)
786 D.Diag(clang::diag::err_drv_argument_only_allowed_with)
787 <<
"fsanitize-minimal-runtime"
788 <<
"fsanitize-trap=cfi";
793 for (
const auto *Arg : Args) {
794 if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
795 int LegacySanitizeCoverage;
796 if (Arg->getNumValues() == 1 &&
797 !StringRef(Arg->getValue(0))
798 .getAsInteger(0, LegacySanitizeCoverage)) {
799 CoverageFeatures = 0;
801 if (LegacySanitizeCoverage != 0 && DiagnoseErrors) {
802 D.Diag(diag::warn_drv_deprecated_arg)
803 << Arg->getAsString(Args) <<
true
804 <<
"-fsanitize-coverage=trace-pc-guard";
815 CoverageFeatures = 0;
817 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
819 CoverageFeatures &= ~parseCoverageFeatures(
D, Arg, DiagnoseErrors);
823 if (DiagnoseErrors) {
825 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
826 <<
"-fsanitize-coverage=func"
827 <<
"-fsanitize-coverage=bb";
829 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
830 <<
"-fsanitize-coverage=func"
831 <<
"-fsanitize-coverage=edge";
833 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
834 <<
"-fsanitize-coverage=bb"
835 <<
"-fsanitize-coverage=edge";
839 D.Diag(clang::diag::warn_drv_deprecated_arg)
840 <<
"-fsanitize-coverage=trace-bb" <<
true
841 <<
"-fsanitize-coverage=trace-pc-guard";
843 D.Diag(clang::diag::warn_drv_deprecated_arg)
844 <<
"-fsanitize-coverage=8bit-counters" <<
true
845 <<
"-fsanitize-coverage=trace-pc-guard";
853 if ((CoverageFeatures & InsertionPointTypes) &&
854 !(CoverageFeatures & InstrumentationTypes) && DiagnoseErrors) {
855 D.Diag(clang::diag::warn_drv_deprecated_arg)
856 <<
"-fsanitize-coverage=[func|bb|edge]" <<
true
857 <<
"-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc],["
862 if (!(CoverageFeatures & InsertionPointTypes)) {
863 if (CoverageFeatures &
876 if (CoverageFeatures) {
878 D, Args, CoverageAllowlistFiles,
879 options::OPT_fsanitize_coverage_allowlist, OptSpecifier(),
880 clang::diag::err_drv_malformed_sanitizer_coverage_allowlist,
883 D, Args, CoverageIgnorelistFiles,
884 options::OPT_fsanitize_coverage_ignorelist, OptSpecifier(),
885 clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist,
890 for (
const auto *Arg :
891 Args.filtered(options::OPT_fexperimental_sanitize_metadata_EQ,
892 options::OPT_fno_experimental_sanitize_metadata_EQ)) {
893 if (Arg->getOption().matches(
894 options::OPT_fexperimental_sanitize_metadata_EQ)) {
896 BinaryMetadataFeatures |=
900 BinaryMetadataFeatures &=
901 ~parseBinaryMetadataFeatures(
D, Arg, DiagnoseErrors);
906 if (BinaryMetadataFeatures) {
908 D, Args, BinaryMetadataIgnorelistFiles,
909 options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ,
911 clang::diag::err_drv_malformed_sanitizer_metadata_ignorelist,
916 Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan,
920 ImplicitCfiRuntime = TC.
getTriple().isAndroid();
922 if (AllAddedKinds & SanitizerKind::Address) {
925 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
926 StringRef S = A->getValue();
928 if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
929 AsanFieldPadding > 2) &&
931 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
935 if (Arg *WindowsDebugRTArg =
936 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
937 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
938 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
939 switch (WindowsDebugRTArg->getOption().getID()) {
940 case options::OPT__SLASH_MTd:
941 case options::OPT__SLASH_MDd:
942 case options::OPT__SLASH_LDd:
943 if (DiagnoseErrors) {
944 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
945 << WindowsDebugRTArg->getAsString(Args)
947 D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
952 StableABI = Args.hasFlag(options::OPT_fsanitize_stable_abi,
953 options::OPT_fno_sanitize_stable_abi,
false);
955 AsanUseAfterScope = Args.hasFlag(
956 options::OPT_fsanitize_address_use_after_scope,
957 options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);
959 AsanPoisonCustomArrayCookie = Args.hasFlag(
960 options::OPT_fsanitize_address_poison_custom_array_cookie,
961 options::OPT_fno_sanitize_address_poison_custom_array_cookie,
962 AsanPoisonCustomArrayCookie);
964 AsanOutlineInstrumentation =
965 Args.hasFlag(options::OPT_fsanitize_address_outline_instrumentation,
966 options::OPT_fno_sanitize_address_outline_instrumentation,
967 AsanOutlineInstrumentation);
969 AsanGlobalsDeadStripping = Args.hasFlag(
970 options::OPT_fsanitize_address_globals_dead_stripping,
971 options::OPT_fno_sanitize_address_globals_dead_stripping,
true);
977 AsanUseOdrIndicator =
978 Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
979 options::OPT_fno_sanitize_address_use_odr_indicator,
982 if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) {
983 AsanInvalidPointerCmp =
true;
986 if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) {
987 AsanInvalidPointerSub =
true;
991 (Args.hasArg(options::OPT_mkernel) ||
992 Args.hasArg(options::OPT_fapple_kext))) {
993 AsanDtorKind = llvm::AsanDtorKind::None;
996 if (
const auto *Arg =
997 Args.getLastArg(options::OPT_sanitize_address_destructor_EQ)) {
999 if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid && DiagnoseErrors) {
1000 TC.
getDriver().
Diag(clang::diag::err_drv_unsupported_option_argument)
1001 << Arg->getSpelling() << Arg->getValue();
1003 AsanDtorKind = parsedAsanDtorKind;
1006 if (
const auto *Arg = Args.getLastArg(
1007 options::OPT_sanitize_address_use_after_return_EQ)) {
1008 auto parsedAsanUseAfterReturn =
1010 if (parsedAsanUseAfterReturn ==
1011 llvm::AsanDetectStackUseAfterReturnMode::Invalid &&
1013 TC.
getDriver().
Diag(clang::diag::err_drv_unsupported_option_argument)
1014 << Arg->getSpelling() << Arg->getValue();
1016 AsanUseAfterReturn = parsedAsanUseAfterReturn;
1020 AsanUseAfterScope =
false;
1023 SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract;
1024 if ((AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) &&
1026 TC.
getDriver().
Diag(clang::diag::err_drv_argument_only_allowed_with)
1028 SanitizerKind::PointerCompare |
1029 SanitizerKind::PointerSubtract)
1030 <<
"-fsanitize=address";
1034 if (AllAddedKinds & SanitizerKind::HWAddress) {
1035 if (Arg *HwasanAbiArg =
1036 Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {
1037 HwasanAbi = HwasanAbiArg->getValue();
1038 if (HwasanAbi !=
"platform" && HwasanAbi !=
"interceptor" &&
1040 D.Diag(clang::diag::err_drv_invalid_value)
1041 << HwasanAbiArg->getAsString(Args) << HwasanAbi;
1043 HwasanAbi =
"interceptor";
1045 if (TC.
getTriple().getArch() == llvm::Triple::x86_64)
1046 HwasanUseAliases = Args.hasFlag(
1047 options::OPT_fsanitize_hwaddress_experimental_aliasing,
1048 options::OPT_fno_sanitize_hwaddress_experimental_aliasing,
1052 if (AllAddedKinds & SanitizerKind::SafeStack) {
1059 Args.hasFlag(options::OPT_fsanitize_link_runtime,
1060 options::OPT_fno_sanitize_link_runtime, LinkRuntimes);
1063 LinkCXXRuntimes = Args.hasArg(options::OPT_fsanitize_link_cxx_runtime,
1064 options::OPT_fno_sanitize_link_cxx_runtime,
1068 NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile,
1069 options::OPT_fmemory_profile_EQ,
1070 options::OPT_fno_memory_profile,
false);
1073 Sanitizers.
Mask |= Kinds;
1074 RecoverableSanitizers.
Mask |= RecoverableKinds;
1075 TrapSanitizers.
Mask |= TrappingKinds;
1076 assert(!(RecoverableKinds & TrappingKinds) &&
1077 "Overlap between recoverable and trapping sanitizers");
1082#define SANITIZER(NAME, ID) \
1083 if (Sanitizers.has(SanitizerKind::ID)) { \
1088#include "clang/Basic/Sanitizers.def"
1093 llvm::opt::ArgStringList &CmdArgs,
1094 const char *SCLOptFlag,
1095 const std::vector<std::string> &SCLFiles) {
1096 for (
const auto &SCLPath : SCLFiles) {
1099 CmdArgs.push_back(Args.MakeArgString(SCLOpt));
1104 const llvm::opt::ArgList &Args,
1105 llvm::opt::ArgStringList &CmdArgs,
1106 StringRef SymbolName) {
1108 LinkerOptionFlag =
"--linker-option=/include:";
1109 if (TC.
getTriple().getArch() == llvm::Triple::x86) {
1111 LinkerOptionFlag +=
'_';
1113 LinkerOptionFlag += SymbolName;
1114 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
1118 for (
auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End;
1120 auto It = std::find(Start, End, StringRef(
"+mte"));
1123 if (It > Start && *std::prev(It) == StringRef(
"-target-feature"))
1131 llvm::opt::ArgStringList &CmdArgs,
1139 bool GPUSanitize =
false;
1141 if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
1150 std::pair<int, const char *> CoverageFlags[] = {
1151 std::make_pair(
CoverageFunc,
"-fsanitize-coverage-type=1"),
1152 std::make_pair(
CoverageBB,
"-fsanitize-coverage-type=2"),
1153 std::make_pair(
CoverageEdge,
"-fsanitize-coverage-type=3"),
1162 "-fsanitize-coverage-trace-pc-guard"),
1164 "-fsanitize-coverage-inline-8bit-counters"),
1166 "-fsanitize-coverage-inline-bool-flag"),
1173 for (
auto F : CoverageFlags) {
1174 if (CoverageFeatures & F.first)
1175 CmdArgs.push_back(F.second);
1178 Args, CmdArgs,
"-fsanitize-coverage-allowlist=", CoverageAllowlistFiles);
1180 CoverageIgnorelistFiles);
1185 const std::pair<int, std::string> BinaryMetadataFlags[] = {
1189 for (
const auto &F : BinaryMetadataFlags) {
1190 if (BinaryMetadataFeatures & F.first)
1192 Args.MakeArgString(
"-fexperimental-sanitize-metadata=" + F.second));
1195 "-fexperimental-sanitize-metadata-ignorelist=",
1196 BinaryMetadataIgnorelistFiles);
1200 Args.hasFlag(options::OPT_frtlib_defaultlib,
1201 options::OPT_fno_rtlib_defaultlib,
true)) {
1205 Args.MakeArgString(
"--dependent-lib=" +
1208 CmdArgs.push_back(Args.MakeArgString(
1209 "--dependent-lib=" +
1213 Args.hasFlag(options::OPT_frtlib_defaultlib,
1214 options::OPT_fno_rtlib_defaultlib,
true)) {
1215 CmdArgs.push_back(Args.MakeArgString(
1222 CmdArgs.push_back(Args.MakeArgString(
1227 if (Sanitizers.
empty())
1229 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize=" +
toString(Sanitizers)));
1231 if (!RecoverableSanitizers.
empty())
1232 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-recover=" +
1235 if (!TrapSanitizers.
empty())
1237 Args.MakeArgString(
"-fsanitize-trap=" +
toString(TrapSanitizers)));
1240 "-fsanitize-ignorelist=", UserIgnorelistFiles);
1242 "-fsanitize-system-ignorelist=", SystemIgnorelistFiles);
1244 if (MsanTrackOrigins)
1245 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-memory-track-origins=" +
1246 Twine(MsanTrackOrigins)));
1248 if (MsanUseAfterDtor)
1249 CmdArgs.push_back(
"-fsanitize-memory-use-after-dtor");
1251 if (!MsanParamRetval)
1252 CmdArgs.push_back(
"-fno-sanitize-memory-param-retval");
1255 if (!TsanMemoryAccess) {
1256 CmdArgs.push_back(
"-mllvm");
1257 CmdArgs.push_back(
"-tsan-instrument-memory-accesses=0");
1258 CmdArgs.push_back(
"-mllvm");
1259 CmdArgs.push_back(
"-tsan-instrument-memintrinsics=0");
1261 if (!TsanFuncEntryExit) {
1262 CmdArgs.push_back(
"-mllvm");
1263 CmdArgs.push_back(
"-tsan-instrument-func-entry-exit=0");
1266 CmdArgs.push_back(
"-mllvm");
1267 CmdArgs.push_back(
"-tsan-instrument-atomics=0");
1270 if (HwasanUseAliases) {
1271 CmdArgs.push_back(
"-mllvm");
1272 CmdArgs.push_back(
"-hwasan-experimental-use-page-aliases=1");
1276 CmdArgs.push_back(
"-fsanitize-cfi-cross-dso");
1278 if (CfiICallGeneralizePointers)
1279 CmdArgs.push_back(
"-fsanitize-cfi-icall-generalize-pointers");
1281 if (CfiICallNormalizeIntegers)
1282 CmdArgs.push_back(
"-fsanitize-cfi-icall-experimental-normalize-integers");
1284 if (CfiCanonicalJumpTables)
1285 CmdArgs.push_back(
"-fsanitize-cfi-canonical-jump-tables");
1288 CmdArgs.push_back(
"-fsanitize-stats");
1291 CmdArgs.push_back(
"-fsanitize-minimal-runtime");
1293 if (AsanFieldPadding)
1294 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-address-field-padding=" +
1295 Twine(AsanFieldPadding)));
1297 if (AsanUseAfterScope)
1298 CmdArgs.push_back(
"-fsanitize-address-use-after-scope");
1300 if (AsanPoisonCustomArrayCookie)
1301 CmdArgs.push_back(
"-fsanitize-address-poison-custom-array-cookie");
1303 if (AsanGlobalsDeadStripping)
1304 CmdArgs.push_back(
"-fsanitize-address-globals-dead-stripping");
1306 if (!AsanUseOdrIndicator)
1307 CmdArgs.push_back(
"-fno-sanitize-address-use-odr-indicator");
1309 if (AsanInvalidPointerCmp) {
1310 CmdArgs.push_back(
"-mllvm");
1311 CmdArgs.push_back(
"-asan-detect-invalid-pointer-cmp");
1314 if (AsanInvalidPointerSub) {
1315 CmdArgs.push_back(
"-mllvm");
1316 CmdArgs.push_back(
"-asan-detect-invalid-pointer-sub");
1319 if (AsanOutlineInstrumentation) {
1320 CmdArgs.push_back(
"-mllvm");
1321 CmdArgs.push_back(
"-asan-instrumentation-with-call-threshold=0");
1328 CmdArgs.push_back(
"-mllvm");
1329 CmdArgs.push_back(
"-asan-instrumentation-with-call-threshold=0");
1330 CmdArgs.push_back(
"-mllvm");
1331 CmdArgs.push_back(
"-asan-max-inline-poisoning-size=0");
1332 CmdArgs.push_back(
"-mllvm");
1333 CmdArgs.push_back(
"-asan-guard-against-version-mismatch=0");
1338 if (AsanDtorKind != llvm::AsanDtorKind::Invalid) {
1339 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-address-destructor=" +
1343 if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
1344 CmdArgs.push_back(Args.MakeArgString(
1345 "-fsanitize-address-use-after-return=" +
1349 if (!HwasanAbi.empty()) {
1350 CmdArgs.push_back(
"-default-function-attr");
1351 CmdArgs.push_back(Args.MakeArgString(
"hwasan-abi=" + HwasanAbi));
1354 if (Sanitizers.
has(SanitizerKind::HWAddress) && !HwasanUseAliases) {
1355 CmdArgs.push_back(
"-target-feature");
1356 CmdArgs.push_back(
"+tagged-globals");
1364 if (Sanitizers.
has(SanitizerKind::Memory) ||
1365 Sanitizers.
has(SanitizerKind::Address))
1366 CmdArgs.push_back(
"-fno-assume-sane-operator-new");
1373 if (Sanitizers.
has(SanitizerKind::FuzzerNoLink)) {
1374 CmdArgs.push_back(
"-fno-builtin-bcmp");
1375 CmdArgs.push_back(
"-fno-builtin-memcmp");
1376 CmdArgs.push_back(
"-fno-builtin-strncmp");
1377 CmdArgs.push_back(
"-fno-builtin-strcmp");
1378 CmdArgs.push_back(
"-fno-builtin-strncasecmp");
1379 CmdArgs.push_back(
"-fno-builtin-strcasecmp");
1380 CmdArgs.push_back(
"-fno-builtin-strstr");
1381 CmdArgs.push_back(
"-fno-builtin-strcasestr");
1382 CmdArgs.push_back(
"-fno-builtin-memmem");
1388 !Args.hasArg(options::OPT_fvisibility_EQ)) {
1389 TC.
getDriver().
Diag(clang::diag::err_drv_argument_only_allowed_with)
1395 if (Sanitizers.
has(SanitizerKind::MemtagStack) &&
1397 TC.
getDriver().
Diag(diag::err_stack_tagging_requires_hardware_feature);
1401 bool DiagnoseErrors) {
1402 assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
1403 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
1404 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
1405 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
1406 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
1407 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) &&
1408 "Invalid argument in parseArgValues!");
1410 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1411 const char *
Value = A->getValue(i);
1414 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
1415 0 == strcmp(
"all",
Value))
1422 else if (DiagnoseErrors)
1423 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1424 << A->getSpelling() <<
Value;
1430 bool DiagnoseErrors) {
1431 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
1432 A->getOption().matches(options::OPT_fno_sanitize_coverage));
1434 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1435 const char *
Value = A->getValue(i);
1436 int F = llvm::StringSwitch<int>(
Value)
1457 if (F == 0 && DiagnoseErrors)
1458 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1459 << A->getSpelling() <<
Value;
1466 bool DiagnoseErrors) {
1468 A->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ) ||
1469 A->getOption().matches(
1470 options::OPT_fno_experimental_sanitize_metadata_EQ));
1472 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1473 const char *
Value = A->getValue(i);
1474 int F = llvm::StringSwitch<int>(
Value)
1480 if (F == 0 && DiagnoseErrors)
1481 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1482 << A->getSpelling() <<
Value;
1490 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
1493 const auto *Arg = *I;
1494 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
1497 if (AddKinds & Mask)
1499 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
1502 Mask &= ~RemoveKinds;
1505 llvm_unreachable(
"arg list didn't provide expected value");
1509 assert(A->getOption().matches(options::OPT_fsanitize_EQ) &&
1510 "Invalid argument in describeSanitizerArg!");
1512 std::string Sanitizers;
1513 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1517 if (!Sanitizers.empty())
1519 Sanitizers += A->getValue(i);
1523 assert(!Sanitizers.empty() &&
"arg didn't provide expected value");
1524 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
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.