clang: lib/Driver/SanitizerArgs.cpp Source File (original) (raw)
1
2
3
4
5
6
7
13#include "llvm/ADT/SmallVector.h"
14#include "llvm/ADT/StringRef.h"
15#include "llvm/ADT/StringSwitch.h"
16#include "llvm/Support/Path.h"
17#include "llvm/Support/SpecialCaseList.h"
18#include "llvm/Support/VirtualFileSystem.h"
19#include "llvm/TargetParser/AArch64TargetParser.h"
20#include "llvm/TargetParser/RISCVTargetParser.h"
21#include "llvm/TargetParser/TargetParser.h"
22#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
23#include
24
25using namespace clang;
28
30 SanitizerKind::Undefined | SanitizerKind::Integer |
31 SanitizerKind::LocalBounds | SanitizerKind::ImplicitConversion |
32 SanitizerKind::Nullability | SanitizerKind::CFI |
33 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;
35 SanitizerKind::Vptr | SanitizerKind::CFI;
39 SanitizerKind::Function | SanitizerKind::KCFI;
41 SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Type |
42 SanitizerKind::Thread | SanitizerKind::Memory | SanitizerKind::DataFlow |
43 SanitizerKind::NumericalStability;
45 SanitizerKind::Address | SanitizerKind::HWAddress |
46 SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |
47 SanitizerKind::Type | SanitizerKind::MemtagStack |
48 SanitizerKind::MemtagHeap | SanitizerKind::MemtagGlobals |
49 SanitizerKind::Memory | SanitizerKind::KernelMemory | SanitizerKind::Leak |
50 SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::Bounds |
51 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
52 SanitizerKind::DataFlow | SanitizerKind::Fuzzer |
53 SanitizerKind::FuzzerNoLink | SanitizerKind::FloatDivideByZero |
54 SanitizerKind::SafeStack | SanitizerKind::ShadowCallStack |
55 SanitizerKind::Thread | SanitizerKind::ObjCCast | SanitizerKind::KCFI |
56 SanitizerKind::NumericalStability;
58 SanitizerKind::Undefined | SanitizerKind::Integer |
59 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
60 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;
62 SanitizerKind::Unreachable | SanitizerKind::Return;
64 SanitizerKind::KernelHWAddress |
65 SanitizerKind::KCFI;
68 (SanitizerKind::Undefined & ~SanitizerKind::Vptr) | SanitizerKind::Integer |
69 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
70 SanitizerKind::LocalBounds | SanitizerKind::CFI |
71 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;
74 SanitizerKind::CFI | SanitizerKind::LocalBounds;
76 SanitizerKind::CFIVCall | SanitizerKind::CFINVCall |
77 SanitizerKind::CFIMFCall | SanitizerKind::CFIDerivedCast |
78 SanitizerKind::CFIUnrelatedCast;
80 TrappingSupported | SanitizerKind::Scudo | SanitizerKind::ShadowCallStack |
81 SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap |
82 SanitizerKind::MemtagGlobals | SanitizerKind::KCFI;
83
104};
105
110};
111
112
113
115 bool DiagnoseErrors);
116
117
118
119
122
123
124
126 bool DiagnoseErrors);
127
128
129
131 const llvm::opt::Arg *A,
132 bool DiagnoseErrors);
133
134
135
137 bool DiagnoseErrors);
138
139
140
141
142
144 const llvm::opt::ArgList &Args,
146
147
148
149
150
153
154
155
157
158
159
161 const llvm::opt::ArgList &Args) {
162 if (Triple.isPS5())
163 return true;
164 return Args.hasFlagNoClaim(options::OPT_mexecute_only,
165 options::OPT_mno_execute_only, false);
166}
167
169 std::vectorstd::string &SCLFiles,
170 unsigned MalformedSCLErrorDiagID,
171 bool DiagnoseErrors) {
172 if (SCLFiles.empty())
173 return;
174
175 std::string BLError;
176 std::unique_ptrllvm::SpecialCaseList SCL(
177 llvm::SpecialCaseList::create(SCLFiles, D.getVFS(), BLError));
178 if (!SCL.get() && DiagnoseErrors)
179 D.Diag(MalformedSCLErrorDiagID) << BLError;
180}
181
183 std::vectorstd::string &IgnorelistFiles,
184 bool DiagnoseErrors) {
185 struct Ignorelist {
186 const char *File;
188 } Ignorelists[] = {{"asan_ignorelist.txt", SanitizerKind::Address},
189 {"hwasan_ignorelist.txt", SanitizerKind::HWAddress},
190 {"memtag_ignorelist.txt", SanitizerKind::MemTag},
191 {"msan_ignorelist.txt", SanitizerKind::Memory},
192 {"nsan_ignorelist.txt", SanitizerKind::NumericalStability},
193 {"tsan_ignorelist.txt", SanitizerKind::Thread},
194 {"tysan_blacklist.txt", SanitizerKind::Type},
195 {"dfsan_abilist.txt", SanitizerKind::DataFlow},
196 {"cfi_ignorelist.txt", SanitizerKind::CFI},
197 {"ubsan_ignorelist.txt",
198 SanitizerKind::Undefined | SanitizerKind::Integer |
199 SanitizerKind::Nullability |
200 SanitizerKind::FloatDivideByZero}};
201
202 for (auto BL : Ignorelists) {
203 if (!(Kinds & BL.Mask))
204 continue;
205
207 llvm::sys::path::append(Path, "share", BL.File);
208 if (D.getVFS().exists(Path))
209 IgnorelistFiles.push_back(std::string(Path));
210 else if (BL.Mask == SanitizerKind::CFI && DiagnoseErrors)
211
212
213 D.Diag(clang::diag::err_drv_missing_sanitizer_ignorelist) << Path;
214 }
216 D, IgnorelistFiles, clang::diag::err_drv_malformed_sanitizer_ignorelist,
217 DiagnoseErrors);
218}
219
220
221
223 const llvm::opt::ArgList &Args,
224 std::vectorstd::string &SCLFiles,
225 llvm::opt::OptSpecifier SCLOptionID,
226 llvm::opt::OptSpecifier NoSCLOptionID,
227 unsigned MalformedSCLErrorDiagID,
228 bool DiagnoseErrors) {
229 for (const auto *Arg : Args) {
230
231 if (Arg->getOption().matches(SCLOptionID)) {
232 Arg->claim();
233 std::string SCLPath = Arg->getValue();
234 if (D.getVFS().exists(SCLPath)) {
235 SCLFiles.push_back(SCLPath);
236 } else if (DiagnoseErrors) {
237 D.Diag(clang::diag::err_drv_no_such_file) << SCLPath;
238 }
239
240 } else if (Arg->getOption().matches(NoSCLOptionID)) {
241 Arg->claim();
242 SCLFiles.clear();
243 }
244 }
246 DiagnoseErrors);
247}
248
249
250
252#define SANITIZER(NAME, ID)
253#define SANITIZER_GROUP(NAME, ID, ALIAS) \
254 if (Kinds & SanitizerKind::ID) \
255 Kinds |= SanitizerKind::ID##Group;
256#include "clang/Basic/Sanitizers.def"
257 return Kinds;
258}
259
260
261
262
263
264
265
270 int OptOutID) {
271 assert(!(AlwaysIn & AlwaysOut) &&
272 "parseSanitizeArgs called with contradictory in/out requirements");
273
275
276
279 for (const auto *Arg : Args) {
280 if (Arg->getOption().matches(OptInID)) {
282
283
285 Add & AlwaysOut & ~DiagnosedAlwaysOutViolations) {
286 if (DiagnoseErrors) {
288 SetToDiagnose.Mask |= KindsToDiagnose;
289 D.Diag(diag::err_drv_unsupported_option_argument)
290 << Arg->getSpelling() << toString(SetToDiagnose);
291 DiagnosedAlwaysOutViolations |= KindsToDiagnose;
292 }
293 }
295 Arg->claim();
296 } else if (Arg->getOption().matches(OptOutID)) {
298
299
301 Remove & AlwaysIn & ~DiagnosedAlwaysInViolations) {
302 if (DiagnoseErrors) {
304 SetToDiagnose.Mask |= KindsToDiagnose;
305 D.Diag(diag::err_drv_unsupported_option_argument)
306 << Arg->getSpelling() << toString(SetToDiagnose);
307 DiagnosedAlwaysInViolations |= KindsToDiagnose;
308 }
309 }
310 Output &= ~expandSanitizerGroups(Remove);
311 Arg->claim();
312 }
313 }
314
315 return Output;
316}
317
319 const llvm::opt::ArgList &Args,
320 bool DiagnoseErrors) {
323
324
325
326
327
329 NeverTrap, options::OPT_fsanitize_trap_EQ,
330 options::OPT_fno_sanitize_trap_EQ);
331}
332
335 bool DiagnoseErrors) {
337 for (const auto *Arg : Args)
338 if (Arg->getOption().matches(options::OPT_fsanitize_skip_hot_cutoff_EQ)) {
339 Arg->claim();
341 }
342
343 return Cutoffs;
344}
345
348}
349
351
355 return false;
356
358 CoverageFeatures;
359}
360
362
363
364
366 ~TrapSanitizers.Mask);
367}
368
370 return !(Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
371 CfiCrossDso && !ImplicitCfiRuntime;
372}
373
375 return (Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
376 CfiCrossDso && !ImplicitCfiRuntime;
377}
378
380
383}
384
386 return static_cast<bool>(Sanitizers.Mask & NeedsLTO);
387}
388
390 const llvm::opt::ArgList &Args,
391 bool DiagnoseErrors) {
392 SanitizerMask AllRemove;
393
394
395 SanitizerMask AllAddedKinds;
396
397
398
399
400 SanitizerMask DiagnosedKinds;
401
404
405 CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
406 options::OPT_fno_sanitize_cfi_cross_dso, false);
407
409
413
414 MinimalRuntime =
415 Args.hasFlag(options::OPT_fsanitize_minimal_runtime,
416 options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime);
417
418
419 Arg *OptLevel = Args.getLastArg(options::OPT_O_Group);
420 bool RemoveObjectSizeAtO0 =
421 !OptLevel || OptLevel->getOption().matches(options::OPT_O0);
422
423 for (const llvm::opt::Arg *Arg : llvm::reverse(Args)) {
424 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
425 Arg->claim();
427
428 if (RemoveObjectSizeAtO0) {
429 AllRemove |= SanitizerKind::ObjectSize;
430
431
432
433 if ((Add & SanitizerKind::ObjectSize) && DiagnoseErrors)
434 D.Diag(diag::warn_drv_object_size_disabled_O0)
435 << Arg->getAsString(Args);
436 }
437
439
440
441 Add &= ~AllRemove;
442
443
444
446 Add & InvalidTrappingKinds & ~DiagnosedKinds) {
447 if (DiagnoseErrors) {
449 D.Diag(diag::err_drv_argument_not_allowed_with)
450 << Desc << "-fsanitize-trap=undefined";
451 }
452 DiagnosedKinds |= KindsToDiagnose;
453 }
454 Add &= ~InvalidTrappingKinds;
455
456 if (MinimalRuntime) {
459 if (DiagnoseErrors) {
461 D.Diag(diag::err_drv_argument_not_allowed_with)
462 << Desc << "-fsanitize-minimal-runtime";
463 }
464 DiagnosedKinds |= KindsToDiagnose;
465 }
466 Add &= ~NotAllowedWithMinimalRuntime;
467 }
468
469 if (llvm::opt::Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
470 StringRef CM = A->getValue();
471 if (CM != "small" &&
472 (Add & SanitizerKind::Function & ~DiagnosedKinds)) {
473 if (DiagnoseErrors)
474 D.Diag(diag::err_drv_argument_only_allowed_with)
475 << "-fsanitize=function"
476 << "-mcmodel=small";
478 DiagnosedKinds |= SanitizerKind::Function;
479 }
480 }
481
482
483
484 const llvm::Triple &Triple = TC.getTriple();
488 if (DiagnoseErrors) {
490 llvm::opt::Arg *A = Args.getLastArgNoClaim(
491 options::OPT_mexecute_only, options::OPT_mno_execute_only);
492 if (A && A->getOption().matches(options::OPT_mexecute_only))
493 D.Diag(diag::err_drv_argument_not_allowed_with)
494 << Desc << A->getAsString(Args);
495 else
496 D.Diag(diag::err_drv_unsupported_opt_for_target)
497 << Desc << Triple.str();
498 }
499 DiagnosedKinds |= KindsToDiagnose;
500 }
501 Add &= ~NotAllowedWithExecuteOnly;
502 }
503
504
505
506
507
508
509
510
511
512
513
514 if (CfiCrossDso && (Add & SanitizerKind::CFIMFCall & ~DiagnosedKinds)) {
515 if (DiagnoseErrors)
516 D.Diag(diag::err_drv_argument_not_allowed_with)
517 << "-fsanitize=cfi-mfcall"
518 << "-fsanitize-cfi-cross-dso";
520 DiagnosedKinds |= SanitizerKind::CFIMFCall;
521 }
522
523 if (SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
524 if (DiagnoseErrors) {
526 D.Diag(diag::err_drv_unsupported_opt_for_target)
528 }
529 DiagnosedKinds |= KindsToDiagnose;
530 }
531 Add &= Supported;
532
533
534
535
537 if (const llvm::opt::Arg *NoRTTIArg = TC.getRTTIArg()) {
538 assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) &&
539 "RTTI disabled without -fno-rtti option?");
540
541
542 if (DiagnoseErrors)
543 D.Diag(diag::err_drv_argument_not_allowed_with)
544 << "-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
545 } else {
546
547
548 if (DiagnoseErrors)
549 D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
550 }
551
552
553 AllRemove |= SanitizerKind::Vptr;
554 }
555
557
558 Add &= ~AllRemove;
559
560
561 Add &= ~InvalidTrappingKinds;
562 if (MinimalRuntime) {
563 Add &= ~NotAllowedWithMinimalRuntime;
564 }
565
566
568 Add &= ~NotAllowedWithExecuteOnly;
569 if (CfiCrossDso)
571
572
573 if (Add & SanitizerKind::UndefinedGroup) {
574 bool S = Args.hasFlagNoClaim(options::OPT_fno_strict_overflow,
575 options::OPT_fstrict_overflow, false);
576 if (Args.hasFlagNoClaim(options::OPT_fwrapv, options::OPT_fno_wrapv, S))
578 }
579 Add &= Supported;
580
581 if (Add & SanitizerKind::Fuzzer)
582 Add |= SanitizerKind::FuzzerNoLink;
583
584
585 if (Add & SanitizerKind::FuzzerNoLink) {
588
591 }
592
593 Kinds |= Add;
594 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
595 Arg->claim();
598 }
599 }
600
601 std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
602 std::make_pair(SanitizerKind::Address,
603 SanitizerKind::Thread | SanitizerKind::Memory),
604 std::make_pair(SanitizerKind::Type,
605 SanitizerKind::Address | SanitizerKind::KernelAddress |
606 SanitizerKind::Memory | SanitizerKind::Leak |
607 SanitizerKind::Thread | SanitizerKind::KernelAddress),
608 std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory),
609 std::make_pair(SanitizerKind::Leak,
610 SanitizerKind::Thread | SanitizerKind::Memory),
611 std::make_pair(SanitizerKind::KernelAddress,
612 SanitizerKind::Address | SanitizerKind::Leak |
613 SanitizerKind::Thread | SanitizerKind::Memory),
614 std::make_pair(SanitizerKind::HWAddress,
615 SanitizerKind::Address | SanitizerKind::Thread |
616 SanitizerKind::Memory | SanitizerKind::KernelAddress),
617 std::make_pair(SanitizerKind::Scudo,
618 SanitizerKind::Address | SanitizerKind::HWAddress |
619 SanitizerKind::Leak | SanitizerKind::Thread |
620 SanitizerKind::Memory | SanitizerKind::KernelAddress),
621 std::make_pair(SanitizerKind::SafeStack,
623 : SanitizerKind::Leak) |
624 SanitizerKind::Address | SanitizerKind::HWAddress |
625 SanitizerKind::Thread | SanitizerKind::Memory |
626 SanitizerKind::KernelAddress),
627 std::make_pair(SanitizerKind::KernelHWAddress,
628 SanitizerKind::Address | SanitizerKind::HWAddress |
629 SanitizerKind::Leak | SanitizerKind::Thread |
630 SanitizerKind::Memory | SanitizerKind::KernelAddress |
631 SanitizerKind::SafeStack),
632 std::make_pair(SanitizerKind::KernelMemory,
633 SanitizerKind::Address | SanitizerKind::HWAddress |
634 SanitizerKind::Leak | SanitizerKind::Thread |
635 SanitizerKind::Memory | SanitizerKind::KernelAddress |
636 SanitizerKind::Scudo | SanitizerKind::SafeStack),
637 std::make_pair(SanitizerKind::MemTag, SanitizerKind::Address |
638 SanitizerKind::KernelAddress |
639 SanitizerKind::HWAddress |
640 SanitizerKind::KernelHWAddress),
641 std::make_pair(SanitizerKind::KCFI, SanitizerKind::Function),
642 std::make_pair(SanitizerKind::Realtime,
643 SanitizerKind::Address | SanitizerKind::Thread |
644 SanitizerKind::Undefined | SanitizerKind::Memory)};
645
646
648
649
650
651 for (auto G : IncompatibleGroups) {
653 if ((Default & Group) && (Kinds & G.second))
655 }
656
658
659
660
663 }
664
665
666 if ((Kinds & NeedsLTO) && .isUsingLTO() && DiagnoseErrors) {
667 D.Diag(diag::err_drv_argument_only_allowed_with)
669 }
670
671 if ((Kinds & SanitizerKind::ShadowCallStack) && TC.getTriple().isAArch64() &&
672 !llvm::AArch64::isX18ReservedByDefault(TC.getTriple()) &&
673 !Args.hasArg(options::OPT_ffixed_x18) && DiagnoseErrors) {
674 D.Diag(diag::err_drv_argument_only_allowed_with)
676 << "-ffixed-x18";
677 }
678
679
680
681
682
683 if (~Supported & SanitizerKind::Vptr) {
685
686
687 if (TC.getTriple().isOSWindows())
689 if (KindsToDiagnose) {
691 S.Mask = KindsToDiagnose;
692 if (DiagnoseErrors)
693 D.Diag(diag::err_drv_unsupported_opt_for_target)
694 << ("-fno-sanitize-trap=" + toString(S)) << TC.getTriple().str();
695 Kinds &= ~KindsToDiagnose;
696 }
697 }
698
699
700 for (auto G : IncompatibleGroups) {
702 if (Kinds & Group) {
703 if (SanitizerMask Incompatible = Kinds & G.second) {
704 if (DiagnoseErrors)
705 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
708 Kinds &= ~Incompatible;
709 }
710 }
711 }
712
713
714
715
716
717
720 Unrecoverable, options::OPT_fsanitize_recover_EQ,
721 options::OPT_fno_sanitize_recover_EQ);
723 RecoverableKinds &= ~Unrecoverable;
724 RecoverableKinds &= Kinds;
725
726 TrappingKinds &= Kinds;
727 RecoverableKinds &= ~TrappingKinds;
728
729
732 options::OPT_fsanitize_merge_handlers_EQ,
733 options::OPT_fno_sanitize_merge_handlers_EQ);
734 MergeKinds &= Kinds;
735
736
738
739
740
741
742 if (!Args.hasArgNoClaim(options::OPT_fno_sanitize_ignorelist))
744
745
746
748 D, Args, UserIgnorelistFiles, options::OPT_fsanitize_ignorelist_EQ,
749 options::OPT_fno_sanitize_ignorelist,
750 clang::diag::err_drv_malformed_sanitizer_ignorelist, DiagnoseErrors);
751
752
753 if (AllAddedKinds & SanitizerKind::Memory) {
754 if (Arg *A =
755 Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
756 options::OPT_fno_sanitize_memory_track_origins)) {
757 if (!A->getOption().matches(
758 options::OPT_fno_sanitize_memory_track_origins)) {
759 StringRef S = A->getValue();
760 if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
761 MsanTrackOrigins > 2) {
762 if (DiagnoseErrors)
763 D.Diag(clang::diag::err_drv_invalid_value)
764 << A->getAsString(Args) << S;
765 }
766 }
767 }
768 MsanUseAfterDtor = Args.hasFlag(
769 options::OPT_fsanitize_memory_use_after_dtor,
770 options::OPT_fno_sanitize_memory_use_after_dtor, MsanUseAfterDtor);
771 MsanParamRetval = Args.hasFlag(
772 options::OPT_fsanitize_memory_param_retval,
773 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
774 } else if (AllAddedKinds & SanitizerKind::KernelMemory) {
775 MsanUseAfterDtor = false;
776 MsanParamRetval = Args.hasFlag(
777 options::OPT_fsanitize_memory_param_retval,
778 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
779 } else {
780 MsanUseAfterDtor = false;
781 MsanParamRetval = false;
782 }
783
784 if (AllAddedKinds & SanitizerKind::MemTag) {
785 StringRef S =
786 Args.getLastArgValue(options::OPT_fsanitize_memtag_mode_EQ, "sync");
787 if (S == "async" || S == "sync") {
788 MemtagMode = S.str();
789 } else {
790 D.Diag(clang::diag::err_drv_invalid_value_with_suggestion)
791 << "-fsanitize-memtag-mode=" << S << "{async, sync}";
792 MemtagMode = "sync";
793 }
794 }
795
796 if (AllAddedKinds & SanitizerKind::Thread) {
797 TsanMemoryAccess = Args.hasFlag(
798 options::OPT_fsanitize_thread_memory_access,
799 options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess);
800 TsanFuncEntryExit = Args.hasFlag(
801 options::OPT_fsanitize_thread_func_entry_exit,
802 options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit);
803 TsanAtomics =
804 Args.hasFlag(options::OPT_fsanitize_thread_atomics,
805 options::OPT_fno_sanitize_thread_atomics, TsanAtomics);
806 }
807
808 if (AllAddedKinds & SanitizerKind::CFI) {
809
810
811 NeedPIE |= CfiCrossDso;
812 CfiICallGeneralizePointers =
813 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
814
815 CfiICallNormalizeIntegers =
816 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
817
818 if (CfiCrossDso && CfiICallGeneralizePointers && DiagnoseErrors)
819 D.Diag(diag::err_drv_argument_not_allowed_with)
820 << "-fsanitize-cfi-cross-dso"
821 << "-fsanitize-cfi-icall-generalize-pointers";
822
823 CfiCanonicalJumpTables =
824 Args.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables,
825 options::OPT_fno_sanitize_cfi_canonical_jump_tables, true);
826 }
827
828 if (AllAddedKinds & SanitizerKind::KCFI) {
829 CfiICallNormalizeIntegers =
830 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
831
832 if (AllAddedKinds & SanitizerKind::CFI && DiagnoseErrors)
833 D.Diag(diag::err_drv_argument_not_allowed_with)
834 << "-fsanitize=kcfi"
836 }
837
838 Stats = Args.hasFlag(options::OPT_fsanitize_stats,
839 options::OPT_fno_sanitize_stats, false);
840
841 if (MinimalRuntime) {
844 if (IncompatibleMask && DiagnoseErrors)
845 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
846 << "-fsanitize-minimal-runtime"
848
849 SanitizerMask NonTrappingCfi = Kinds & SanitizerKind::CFI & ~TrappingKinds;
850 if (NonTrappingCfi && DiagnoseErrors)
851 D.Diag(clang::diag::err_drv_argument_only_allowed_with)
852 << "fsanitize-minimal-runtime"
853 << "fsanitize-trap=cfi";
854 }
855
856 for (const auto *Arg : Args.filtered(
857 options::OPT_fsanitize_undefined_ignore_overflow_pattern_EQ)) {
858 Arg->claim();
859 OverflowPatternExclusions |=
861 }
862
863
864
865 for (const auto *Arg : Args) {
866 if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
867 int LegacySanitizeCoverage;
868 if (Arg->getNumValues() == 1 &&
869 !StringRef(Arg->getValue(0))
870 .getAsInteger(0, LegacySanitizeCoverage)) {
871 CoverageFeatures = 0;
872 Arg->claim();
873 if (LegacySanitizeCoverage != 0 && DiagnoseErrors) {
874 D.Diag(diag::warn_drv_deprecated_arg)
875 << Arg->getAsString(Args) << true
876 << "-fsanitize-coverage=trace-pc-guard";
877 }
878 continue;
879 }
881
882
883
885 Arg->claim();
886 } else {
887 CoverageFeatures = 0;
888 }
889 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
890 Arg->claim();
891 CoverageFeatures &= ~parseCoverageFeatures(D, Arg, DiagnoseErrors);
892 }
893 }
894
895 if (DiagnoseErrors) {
897 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
898 << "-fsanitize-coverage=func"
899 << "-fsanitize-coverage=bb";
901 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
902 << "-fsanitize-coverage=func"
903 << "-fsanitize-coverage=edge";
905 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
906 << "-fsanitize-coverage=bb"
907 << "-fsanitize-coverage=edge";
908
909
911 D.Diag(clang::diag::warn_drv_deprecated_arg)
912 << "-fsanitize-coverage=trace-bb" << true
913 << "-fsanitize-coverage=trace-pc-guard";
915 D.Diag(clang::diag::warn_drv_deprecated_arg)
916 << "-fsanitize-coverage=8bit-counters" << true
917 << "-fsanitize-coverage=trace-pc-guard";
918 }
919
925 if ((CoverageFeatures & InsertionPointTypes) &&
926 !(CoverageFeatures & InstrumentationTypes) && DiagnoseErrors) {
927 D.Diag(clang::diag::warn_drv_deprecated_arg)
928 << "-fsanitize-coverage=[func|bb|edge]" << true
929 << "-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc],["
930 "control-flow]";
931 }
932
933
934 if (!(CoverageFeatures & InsertionPointTypes)) {
935 if (CoverageFeatures &
939
942 }
943
944
945
946
947
948 if (CoverageFeatures) {
950 D, Args, CoverageAllowlistFiles,
951 options::OPT_fsanitize_coverage_allowlist, OptSpecifier(),
952 clang::diag::err_drv_malformed_sanitizer_coverage_allowlist,
953 DiagnoseErrors);
955 D, Args, CoverageIgnorelistFiles,
956 options::OPT_fsanitize_coverage_ignorelist, OptSpecifier(),
957 clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist,
958 DiagnoseErrors);
959 }
960
961
962 for (const auto *Arg :
963 Args.filtered(options::OPT_fexperimental_sanitize_metadata_EQ,
964 options::OPT_fno_experimental_sanitize_metadata_EQ)) {
965 if (Arg->getOption().matches(
966 options::OPT_fexperimental_sanitize_metadata_EQ)) {
967 Arg->claim();
968 BinaryMetadataFeatures |=
970 } else {
971 Arg->claim();
972 BinaryMetadataFeatures &=
973 ~parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);
974 }
975 }
976
977
978 if (BinaryMetadataFeatures) {
980 D, Args, BinaryMetadataIgnorelistFiles,
981 options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ,
982 OptSpecifier(),
983 clang::diag::err_drv_malformed_sanitizer_metadata_ignorelist,
984 DiagnoseErrors);
985 }
986
987 SharedRuntime = Args.hasFlag(
988 options::OPT_shared_libsan, options::OPT_static_libsan,
991 if (!SharedRuntime && TC.getTriple().isOSWindows()) {
992 Arg *A =
993 Args.getLastArg(options::OPT_shared_libsan, options::OPT_static_libsan);
994 D.Diag(clang::diag::err_drv_unsupported_opt_for_target)
995 << A->getSpelling() << TC.getTriple().str();
996 }
997
998 ImplicitCfiRuntime = TC.getTriple().isAndroid();
999
1000 if (AllAddedKinds & SanitizerKind::Address) {
1001 NeedPIE |= TC.getTriple().isOSFuchsia();
1002 if (Arg *A =
1003 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
1004 StringRef S = A->getValue();
1005
1006 if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
1007 AsanFieldPadding > 2) &&
1008 DiagnoseErrors) {
1009 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
1010 }
1011 }
1012
1013 if (Arg *WindowsDebugRTArg =
1014 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
1015 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
1016 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
1017 switch (WindowsDebugRTArg->getOption().getID()) {
1018 case options::OPT__SLASH_MTd:
1019 case options::OPT__SLASH_MDd:
1020 case options::OPT__SLASH_LDd:
1021 if (DiagnoseErrors) {
1022 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
1023 << WindowsDebugRTArg->getAsString(Args)
1025 D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
1026 }
1027 }
1028 }
1029
1030 StableABI = Args.hasFlag(options::OPT_fsanitize_stable_abi,
1031 options::OPT_fno_sanitize_stable_abi, false);
1032
1033 AsanUseAfterScope = Args.hasFlag(
1034 options::OPT_fsanitize_address_use_after_scope,
1035 options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);
1036
1037 AsanPoisonCustomArrayCookie = Args.hasFlag(
1038 options::OPT_fsanitize_address_poison_custom_array_cookie,
1039 options::OPT_fno_sanitize_address_poison_custom_array_cookie,
1040 AsanPoisonCustomArrayCookie);
1041
1042 AsanOutlineInstrumentation =
1043 Args.hasFlag(options::OPT_fsanitize_address_outline_instrumentation,
1044 options::OPT_fno_sanitize_address_outline_instrumentation,
1045 AsanOutlineInstrumentation);
1046
1047 AsanGlobalsDeadStripping = Args.hasFlag(
1048 options::OPT_fsanitize_address_globals_dead_stripping,
1049 options::OPT_fno_sanitize_address_globals_dead_stripping, true);
1050
1051
1052
1053
1054
1055 AsanUseOdrIndicator =
1056 Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
1057 options::OPT_fno_sanitize_address_use_odr_indicator,
1059
1060 if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) {
1061 AsanInvalidPointerCmp = true;
1062 }
1063
1064 if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) {
1065 AsanInvalidPointerSub = true;
1066 }
1067
1068 if (TC.getTriple().isOSDarwin() &&
1069 (Args.hasArg(options::OPT_mkernel) ||
1070 Args.hasArg(options::OPT_fapple_kext))) {
1071 AsanDtorKind = llvm::AsanDtorKind::None;
1072 }
1073
1074 if (const auto *Arg =
1075 Args.getLastArg(options::OPT_sanitize_address_destructor_EQ)) {
1077 if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid && DiagnoseErrors) {
1078 TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)
1079 << Arg->getSpelling() << Arg->getValue();
1080 }
1081 AsanDtorKind = parsedAsanDtorKind;
1082 }
1083
1084 if (const auto *Arg = Args.getLastArg(
1085 options::OPT_sanitize_address_use_after_return_EQ)) {
1086 auto parsedAsanUseAfterReturn =
1088 if (parsedAsanUseAfterReturn ==
1089 llvm::AsanDetectStackUseAfterReturnMode::Invalid &&
1090 DiagnoseErrors) {
1091 TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)
1092 << Arg->getSpelling() << Arg->getValue();
1093 }
1094 AsanUseAfterReturn = parsedAsanUseAfterReturn;
1095 }
1096
1097 } else {
1098 AsanUseAfterScope = false;
1099
1101 SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract;
1102 if ((AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) &&
1103 DiagnoseErrors) {
1104 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)
1106 SanitizerKind::PointerCompare |
1107 SanitizerKind::PointerSubtract)
1108 << "-fsanitize=address";
1109 }
1110 }
1111
1112 if (AllAddedKinds & SanitizerKind::HWAddress) {
1113 if (Arg *HwasanAbiArg =
1114 Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {
1115 HwasanAbi = HwasanAbiArg->getValue();
1116 if (HwasanAbi != "platform" && HwasanAbi != "interceptor" &&
1117 DiagnoseErrors)
1118 D.Diag(clang::diag::err_drv_invalid_value)
1119 << HwasanAbiArg->getAsString(Args) << HwasanAbi;
1120 } else {
1121 HwasanAbi = "interceptor";
1122 }
1123 if (TC.getTriple().getArch() == llvm::Triple::x86_64)
1124 HwasanUseAliases = Args.hasFlag(
1125 options::OPT_fsanitize_hwaddress_experimental_aliasing,
1126 options::OPT_fno_sanitize_hwaddress_experimental_aliasing,
1127 HwasanUseAliases);
1128 }
1129
1130 if (AllAddedKinds & SanitizerKind::SafeStack) {
1131
1132 SafeStackRuntime =
1134 }
1135
1136 LinkRuntimes =
1137 Args.hasFlag(options::OPT_fsanitize_link_runtime,
1138 options::OPT_fno_sanitize_link_runtime, LinkRuntimes);
1139
1140
1141 LinkCXXRuntimes = D.CCCIsCXX();
1142 LinkCXXRuntimes =
1143 Args.hasFlag(options::OPT_fsanitize_link_cxx_runtime,
1144 options::OPT_fno_sanitize_link_cxx_runtime, LinkCXXRuntimes);
1145
1146 NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile,
1147 options::OPT_fmemory_profile_EQ,
1148 options::OPT_fno_memory_profile, false);
1149
1150
1151 Sanitizers.Mask |= Kinds;
1152 RecoverableSanitizers.Mask |= RecoverableKinds;
1153 TrapSanitizers.Mask |= TrappingKinds;
1154 assert(!(RecoverableKinds & TrappingKinds) &&
1155 "Overlap between recoverable and trapping sanitizers");
1156
1157 MergeHandlers.Mask |= MergeKinds;
1158
1159
1160 SkipHotCutoffs.clear(~Sanitizers.Mask);
1161}
1162
1164 std::string Res;
1165#define SANITIZER(NAME, ID) \
1166 if (Sanitizers.has(SanitizerKind::ID)) { \
1167 if (!Res.empty()) \
1168 Res += ","; \
1169 Res += NAME; \
1170 }
1171#include "clang/Basic/Sanitizers.def"
1172 return Res;
1173}
1174
1178 return llvm::join(Res, ",");
1179}
1180
1182 llvm::opt::ArgStringList &CmdArgs,
1183 const char *SCLOptFlag,
1184 const std::vectorstd::string &SCLFiles) {
1185 for (const auto &SCLPath : SCLFiles) {
1187 SCLOpt += SCLPath;
1188 CmdArgs.push_back(Args.MakeArgString(SCLOpt));
1189 }
1190}
1191
1193 const llvm::opt::ArgList &Args,
1194 llvm::opt::ArgStringList &CmdArgs,
1195 StringRef SymbolName) {
1197 LinkerOptionFlag = "--linker-option=/include:";
1198 if (TC.getTriple().getArch() == llvm::Triple::x86) {
1199
1200 LinkerOptionFlag += '_';
1201 }
1202 LinkerOptionFlag += SymbolName;
1203 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
1204}
1205
1207 for (auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End;
1208 ++Start) {
1209 auto It = std::find(Start, End, StringRef("+mte"));
1210 if (It == End)
1211 break;
1212 if (It > Start && *std::prev(It) == StringRef("-target-feature"))
1213 return true;
1214 Start = It;
1215 }
1216 return false;
1217}
1218
1220 llvm::opt::ArgStringList &CmdArgs,
1222
1223
1224
1226 return;
1227
1228 bool GPUSanitize = false;
1229 if (TC.getTriple().isAMDGPU()) {
1230 if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
1231 true))
1232 return;
1233 GPUSanitize = true;
1234 }
1235
1236
1237
1238
1239 std::pair<int, const char *> CoverageFlags[] = {
1240 std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"),
1241 std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"),
1242 std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"),
1243 std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"),
1244 std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"),
1245 std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"),
1246 std::make_pair(CoverageTraceDiv, "-fsanitize-coverage-trace-div"),
1247 std::make_pair(CoverageTraceGep, "-fsanitize-coverage-trace-gep"),
1249 std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"),
1251 "-fsanitize-coverage-trace-pc-guard"),
1253 "-fsanitize-coverage-inline-8bit-counters"),
1255 "-fsanitize-coverage-inline-bool-flag"),
1256 std::make_pair(CoveragePCTable, "-fsanitize-coverage-pc-table"),
1257 std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune"),
1258 std::make_pair(CoverageStackDepth, "-fsanitize-coverage-stack-depth"),
1259 std::make_pair(CoverageTraceLoads, "-fsanitize-coverage-trace-loads"),
1260 std::make_pair(CoverageTraceStores, "-fsanitize-coverage-trace-stores"),
1261 std::make_pair(CoverageControlFlow, "-fsanitize-coverage-control-flow")};
1262 for (auto F : CoverageFlags) {
1263 if (CoverageFeatures & F.first)
1264 CmdArgs.push_back(F.second);
1265 }
1267 Args, CmdArgs, "-fsanitize-coverage-allowlist=", CoverageAllowlistFiles);
1269 CoverageIgnorelistFiles);
1270
1271 if (!GPUSanitize) {
1272
1273
1274 const std::pair<int, std::string> BinaryMetadataFlags[] = {
1278 for (const auto &F : BinaryMetadataFlags) {
1279 if (BinaryMetadataFeatures & F.first)
1280 CmdArgs.push_back(
1281 Args.MakeArgString("-fexperimental-sanitize-metadata=" + F.second));
1282 }
1284 "-fexperimental-sanitize-metadata-ignorelist=",
1285 BinaryMetadataIgnorelistFiles);
1286 }
1287
1289 Args.hasFlag(options::OPT_frtlib_defaultlib,
1290 options::OPT_fno_rtlib_defaultlib, true)) {
1291
1292
1293 CmdArgs.push_back(
1294 Args.MakeArgString("--dependent-lib=" +
1297 CmdArgs.push_back(Args.MakeArgString(
1298 "--dependent-lib=" +
1300 }
1302 Args.hasFlag(options::OPT_frtlib_defaultlib,
1303 options::OPT_fno_rtlib_defaultlib, true)) {
1304 CmdArgs.push_back(Args.MakeArgString(
1306
1307
1308
1309
1310
1311 CmdArgs.push_back(Args.MakeArgString(
1314 }
1315
1316 if (Sanitizers.empty())
1317 return;
1318 CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers)));
1319
1320 if (!RecoverableSanitizers.empty())
1321 CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" +
1322 toString(RecoverableSanitizers)));
1323
1324 if (!TrapSanitizers.empty())
1325 CmdArgs.push_back(
1326 Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));
1327
1328 if (!MergeHandlers.empty())
1329 CmdArgs.push_back(
1330 Args.MakeArgString("-fsanitize-merge=" + toString(MergeHandlers)));
1331
1332 std::string SkipHotCutoffsStr = toString(SkipHotCutoffs);
1333 if (!SkipHotCutoffsStr.empty())
1334 CmdArgs.push_back(
1335 Args.MakeArgString("-fsanitize-skip-hot-cutoff=" + SkipHotCutoffsStr));
1336
1338 "-fsanitize-ignorelist=", UserIgnorelistFiles);
1340 "-fsanitize-system-ignorelist=", SystemIgnorelistFiles);
1341
1342 if (OverflowPatternExclusions)
1343 Args.AddAllArgs(
1344 CmdArgs, options::OPT_fsanitize_undefined_ignore_overflow_pattern_EQ);
1345
1346 if (MsanTrackOrigins)
1347 CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" +
1348 Twine(MsanTrackOrigins)));
1349
1350 if (MsanUseAfterDtor)
1351 CmdArgs.push_back("-fsanitize-memory-use-after-dtor");
1352
1353 if (!MsanParamRetval)
1354 CmdArgs.push_back("-fno-sanitize-memory-param-retval");
1355
1356
1357 if (!TsanMemoryAccess) {
1358 CmdArgs.push_back("-mllvm");
1359 CmdArgs.push_back("-tsan-instrument-memory-accesses=0");
1360 CmdArgs.push_back("-mllvm");
1361 CmdArgs.push_back("-tsan-instrument-memintrinsics=0");
1362 }
1363 if (!TsanFuncEntryExit) {
1364 CmdArgs.push_back("-mllvm");
1365 CmdArgs.push_back("-tsan-instrument-func-entry-exit=0");
1366 }
1367 if (!TsanAtomics) {
1368 CmdArgs.push_back("-mllvm");
1369 CmdArgs.push_back("-tsan-instrument-atomics=0");
1370 }
1371
1372 if (HwasanUseAliases) {
1373 CmdArgs.push_back("-mllvm");
1374 CmdArgs.push_back("-hwasan-experimental-use-page-aliases=1");
1375 }
1376
1377 if (CfiCrossDso)
1378 CmdArgs.push_back("-fsanitize-cfi-cross-dso");
1379
1380 if (CfiICallGeneralizePointers)
1381 CmdArgs.push_back("-fsanitize-cfi-icall-generalize-pointers");
1382
1383 if (CfiICallNormalizeIntegers)
1384 CmdArgs.push_back("-fsanitize-cfi-icall-experimental-normalize-integers");
1385
1386 if (CfiCanonicalJumpTables)
1387 CmdArgs.push_back("-fsanitize-cfi-canonical-jump-tables");
1388
1389 if (Stats)
1390 CmdArgs.push_back("-fsanitize-stats");
1391
1392 if (MinimalRuntime)
1393 CmdArgs.push_back("-fsanitize-minimal-runtime");
1394
1395 if (AsanFieldPadding)
1396 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" +
1397 Twine(AsanFieldPadding)));
1398
1399 if (AsanUseAfterScope)
1400 CmdArgs.push_back("-fsanitize-address-use-after-scope");
1401
1402 if (AsanPoisonCustomArrayCookie)
1403 CmdArgs.push_back("-fsanitize-address-poison-custom-array-cookie");
1404
1405 if (AsanGlobalsDeadStripping)
1406 CmdArgs.push_back("-fsanitize-address-globals-dead-stripping");
1407
1408 if (!AsanUseOdrIndicator)
1409 CmdArgs.push_back("-fno-sanitize-address-use-odr-indicator");
1410
1411 if (AsanInvalidPointerCmp) {
1412 CmdArgs.push_back("-mllvm");
1413 CmdArgs.push_back("-asan-detect-invalid-pointer-cmp");
1414 }
1415
1416 if (AsanInvalidPointerSub) {
1417 CmdArgs.push_back("-mllvm");
1418 CmdArgs.push_back("-asan-detect-invalid-pointer-sub");
1419 }
1420
1421 if (AsanOutlineInstrumentation) {
1422 CmdArgs.push_back("-mllvm");
1423 CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");
1424 }
1425
1426
1427
1428
1429 if (StableABI) {
1430 CmdArgs.push_back("-mllvm");
1431 CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");
1432 CmdArgs.push_back("-mllvm");
1433 CmdArgs.push_back("-asan-max-inline-poisoning-size=0");
1434 CmdArgs.push_back("-mllvm");
1435 CmdArgs.push_back("-asan-guard-against-version-mismatch=0");
1436 }
1437
1438
1439
1440 if (AsanDtorKind != llvm::AsanDtorKind::Invalid) {
1441 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-destructor=" +
1443 }
1444
1445 if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
1446 CmdArgs.push_back(Args.MakeArgString(
1447 "-fsanitize-address-use-after-return=" +
1449 }
1450
1451 if (!HwasanAbi.empty()) {
1452 CmdArgs.push_back("-default-function-attr");
1453 CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi));
1454 }
1455
1456 if (Sanitizers.has(SanitizerKind::HWAddress) && !HwasanUseAliases) {
1457 CmdArgs.push_back("-target-feature");
1458 CmdArgs.push_back("+tagged-globals");
1459 }
1460
1461
1462
1463
1464
1465
1466 if (Sanitizers.has(SanitizerKind::Memory) ||
1467 Sanitizers.has(SanitizerKind::Address))
1468 CmdArgs.push_back("-fno-assume-sane-operator-new");
1469
1470
1471
1472
1473
1474
1475 if (Sanitizers.has(SanitizerKind::FuzzerNoLink)) {
1476 CmdArgs.push_back("-fno-builtin-bcmp");
1477 CmdArgs.push_back("-fno-builtin-memcmp");
1478 CmdArgs.push_back("-fno-builtin-strncmp");
1479 CmdArgs.push_back("-fno-builtin-strcmp");
1480 CmdArgs.push_back("-fno-builtin-strncasecmp");
1481 CmdArgs.push_back("-fno-builtin-strcasecmp");
1482 CmdArgs.push_back("-fno-builtin-strstr");
1483 CmdArgs.push_back("-fno-builtin-strcasestr");
1484 CmdArgs.push_back("-fno-builtin-memmem");
1485 }
1486
1487
1488
1490 !Args.hasArg(options::OPT_fvisibility_EQ)) {
1491 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)
1494 << "-fvisibility=";
1495 }
1496
1497 if (Sanitizers.has(SanitizerKind::MemtagStack) &&
1499 TC.getDriver().Diag(diag::err_stack_tagging_requires_hardware_feature);
1500}
1501
1503 bool DiagnoseErrors) {
1504 assert(
1505 (A->getOption().matches(options::OPT_fsanitize_EQ) ||
1506 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
1507 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
1508 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
1509 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
1510 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ) ||
1511 A->getOption().matches(options::OPT_fsanitize_merge_handlers_EQ) ||
1512 A->getOption().matches(options::OPT_fno_sanitize_merge_handlers_EQ)) &&
1513 "Invalid argument in parseArgValues!");
1515 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1516 const char *Value = A->getValue(i);
1518
1519 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
1520 0 == strcmp("all", Value))
1522 else
1524
1525 if (Kind)
1526 Kinds |= Kind;
1527 else if (DiagnoseErrors)
1528 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1529 << A->getSpelling() << Value;
1530 }
1531 return Kinds;
1532}
1533
1536 assert(A->getOption().matches(options::OPT_fsanitize_skip_hot_cutoff_EQ) &&
1537 "Invalid argument in parseArgCutoffs!");
1538 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1539 const char *Value = A->getValue(i);
1540
1541
1542
1544 DiagnoseErrors)
1545 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1546 << A->getSpelling() << Value;
1547 }
1548}
1549
1551 const llvm::opt::Arg *A,
1552 bool DiagnoseErrors) {
1553 int Exclusions = 0;
1554 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1555 const char *Value = A->getValue(i);
1556 int E =
1557 llvm::StringSwitch(Value)
1560 .Case("add-unsigned-overflow-test",
1562 .Case("add-signed-overflow-test",
1566 .Default(0);
1567 if (E == 0)
1568 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1569 << A->getSpelling() << Value;
1570 Exclusions |= E;
1571 }
1572 return Exclusions;
1573}
1574
1576 bool DiagnoseErrors) {
1577 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
1578 A->getOption().matches(options::OPT_fno_sanitize_coverage));
1579 int Features = 0;
1580 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1581 const char *Value = A->getValue(i);
1582 int F = llvm::StringSwitch(Value)
1602 .Default(0);
1603 if (F == 0 && DiagnoseErrors)
1604 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1605 << A->getSpelling() << Value;
1606 Features |= F;
1607 }
1608 return Features;
1609}
1610
1612 bool DiagnoseErrors) {
1613 assert(
1614 A->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ) ||
1615 A->getOption().matches(
1616 options::OPT_fno_experimental_sanitize_metadata_EQ));
1617 int Features = 0;
1618 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1619 const char *Value = A->getValue(i);
1620 int F = llvm::StringSwitch(Value)
1624 .Case("all", ~0)
1625 .Default(0);
1626 if (F == 0 && DiagnoseErrors)
1627 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1628 << A->getSpelling() << Value;
1629 Features |= F;
1630 }
1631 return Features;
1632}
1633
1636 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
1637 E = Args.rend();
1638 I != E; ++I) {
1639 const auto *Arg = *I;
1640 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
1643 if (AddKinds & Mask)
1645 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
1648 Mask &= ~RemoveKinds;
1649 }
1650 }
1651 llvm_unreachable("arg list didn't provide expected value");
1652}
1653
1655 assert(A->getOption().matches(options::OPT_fsanitize_EQ) &&
1656 "Invalid argument in describeSanitizerArg!");
1657
1658 std::string Sanitizers;
1659 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1662 Mask) {
1663 if (!Sanitizers.empty())
1664 Sanitizers += ",";
1665 Sanitizers += A->getValue(i);
1666 }
1667 }
1668
1669 assert(!Sanitizers.empty() && "arg didn't provide expected value");
1670 return "-fsanitize=" + Sanitizers;
1671}
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 SanitizerMask parseSanitizeArgs(const Driver &D, const llvm::opt::ArgList &Args, bool DiagnoseErrors, SanitizerMask Default, SanitizerMask AlwaysIn, SanitizerMask AlwaysOut, int OptInID, int OptOutID)
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 const SanitizerMask MergeDefault
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 SanitizerMaskCutoffs parseSanitizeSkipHotCutoffArgs(const Driver &D, const llvm::opt::ArgList &Args, bool DiagnoseErrors)
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 void parseArgCutoffs(const Driver &D, const llvm::opt::Arg *A, bool DiagnoseErrors, SanitizerMaskCutoffs &Cutoffs)
Parse a -fsanitize==... or -fno-sanitize= argument's values, diagnosing any inval...
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 int parseOverflowPatternExclusionValues(const Driver &D, const llvm::opt::Arg *A, bool DiagnoseErrors)
Parse -fsanitize-undefined-ignore-overflow-pattern= flag values, diagnosing any invalid values.
static const SanitizerMask NotAllowedWithExecuteOnly
@ CoverageInline8bitCounters
Defines the clang::SanitizerKind enum.
@ None
Don't exclude any overflow patterns from sanitizers.
@ AddUnsignedOverflowTest
if (a + b < a)
@ All
Exclude all overflow patterns (below)
@ AddSignedOverflowTest
if (a + b < a)
@ PostDecrInWhile
while (count–)
void clear(SanitizerMask K=SanitizerKind::All)
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
bool needsUbsanCXXRt() 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)
bool parseSanitizerWeightedValue(StringRef Value, bool AllowGroups, SanitizerMaskCutoffs &Cutoffs)
Parse a single weighted value (e.g., 'undefined=0.05') from a -fsanitize= or -fno-sanitize= value lis...
SanitizerMask expandSanitizerGroups(SanitizerMask Kinds)
For each sanitizer group bit set in Kinds, set the bits for sanitizers this group enables.
void serializeSanitizerMaskCutoffs(const SanitizerMaskCutoffs &Cutoffs, SmallVectorImpl< std::string > &Values)
Serialize a SanitizerMaskCutoffs into values for -fsanitize= or -fno-sanitize=.
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.