1 //===--- SanitizerArgs.cpp - Arguments for sanitizer tools ---------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
8 #include "clang/Driver/SanitizerArgs.h"
9 #include "ToolChains/CommonArgs.h"
10 #include "clang/Basic/Sanitizers.h"
11 #include "clang/Driver/Driver.h"
12 #include "clang/Driver/DriverDiagnostic.h"
13 #include "clang/Driver/Options.h"
14 #include "clang/Driver/ToolChain.h"
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"
27 using namespace clang
;
28 using namespace clang::driver
;
29 using namespace llvm::opt
;
31 static const SanitizerMask NeedsUbsanRt
=
32 SanitizerKind::Undefined
| SanitizerKind::Integer
|
33 SanitizerKind::ImplicitConversion
| SanitizerKind::Nullability
|
34 SanitizerKind::CFI
| SanitizerKind::FloatDivideByZero
|
35 SanitizerKind::ObjCCast
;
36 static const SanitizerMask NeedsUbsanCxxRt
=
37 SanitizerKind::Vptr
| SanitizerKind::CFI
;
38 static const SanitizerMask NotAllowedWithTrap
= SanitizerKind::Vptr
;
39 static const SanitizerMask NotAllowedWithMinimalRuntime
= SanitizerKind::Vptr
;
40 static const SanitizerMask NotAllowedWithExecuteOnly
=
41 SanitizerKind::Function
| SanitizerKind::KCFI
;
42 static const SanitizerMask NeedsUnwindTables
=
43 SanitizerKind::Address
| SanitizerKind::HWAddress
| SanitizerKind::Thread
|
44 SanitizerKind::Memory
| SanitizerKind::DataFlow
;
45 static const SanitizerMask SupportsCoverage
=
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
;
57 static const SanitizerMask RecoverableByDefault
=
58 SanitizerKind::Undefined
| SanitizerKind::Integer
|
59 SanitizerKind::ImplicitConversion
| SanitizerKind::Nullability
|
60 SanitizerKind::FloatDivideByZero
| SanitizerKind::ObjCCast
;
61 static const SanitizerMask Unrecoverable
=
62 SanitizerKind::Unreachable
| SanitizerKind::Return
;
63 static const SanitizerMask AlwaysRecoverable
= SanitizerKind::KernelAddress
|
64 SanitizerKind::KernelHWAddress
|
66 static const SanitizerMask NeedsLTO
= SanitizerKind::CFI
;
67 static const SanitizerMask TrappingSupported
=
68 (SanitizerKind::Undefined
& ~SanitizerKind::Vptr
) | SanitizerKind::Integer
|
69 SanitizerKind::Nullability
| SanitizerKind::LocalBounds
|
70 SanitizerKind::CFI
| SanitizerKind::FloatDivideByZero
|
71 SanitizerKind::ObjCCast
;
72 static const SanitizerMask TrappingDefault
= SanitizerKind::CFI
;
73 static const SanitizerMask CFIClasses
=
74 SanitizerKind::CFIVCall
| SanitizerKind::CFINVCall
|
75 SanitizerKind::CFIMFCall
| SanitizerKind::CFIDerivedCast
|
76 SanitizerKind::CFIUnrelatedCast
;
77 static const SanitizerMask CompatibleWithMinimalRuntime
=
78 TrappingSupported
| SanitizerKind::Scudo
| SanitizerKind::ShadowCallStack
|
79 SanitizerKind::MemtagStack
| SanitizerKind::MemtagHeap
|
80 SanitizerKind::MemtagGlobals
| SanitizerKind::KCFI
;
82 enum CoverageFeature
{
83 CoverageFunc
= 1 << 0,
85 CoverageEdge
= 1 << 2,
86 CoverageIndirCall
= 1 << 3,
87 CoverageTraceBB
= 1 << 4, // Deprecated.
88 CoverageTraceCmp
= 1 << 5,
89 CoverageTraceDiv
= 1 << 6,
90 CoverageTraceGep
= 1 << 7,
91 Coverage8bitCounters
= 1 << 8, // Deprecated.
92 CoverageTracePC
= 1 << 9,
93 CoverageTracePCGuard
= 1 << 10,
94 CoverageNoPrune
= 1 << 11,
95 CoverageInline8bitCounters
= 1 << 12,
96 CoveragePCTable
= 1 << 13,
97 CoverageStackDepth
= 1 << 14,
98 CoverageInlineBoolFlag
= 1 << 15,
99 CoverageTraceLoads
= 1 << 16,
100 CoverageTraceStores
= 1 << 17,
101 CoverageControlFlow
= 1 << 18,
104 enum BinaryMetadataFeature
{
105 BinaryMetadataCovered
= 1 << 0,
106 BinaryMetadataAtomics
= 1 << 1,
107 BinaryMetadataUAR
= 1 << 2,
110 /// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
111 /// invalid components. Returns a SanitizerMask.
112 static SanitizerMask
parseArgValues(const Driver
&D
, const llvm::opt::Arg
*A
,
113 bool DiagnoseErrors
);
115 /// Parse -f(no-)?sanitize-coverage= flag values, diagnosing any invalid
116 /// components. Returns OR of members of \c CoverageFeature enumeration.
117 static int parseCoverageFeatures(const Driver
&D
, const llvm::opt::Arg
*A
,
118 bool DiagnoseErrors
);
120 /// Parse -f(no-)?sanitize-metadata= flag values, diagnosing any invalid
121 /// components. Returns OR of members of \c BinaryMetadataFeature enumeration.
122 static int parseBinaryMetadataFeatures(const Driver
&D
, const llvm::opt::Arg
*A
,
123 bool DiagnoseErrors
);
125 /// Produce an argument string from ArgList \p Args, which shows how it
126 /// provides some sanitizer kind from \p Mask. For example, the argument list
127 /// "-fsanitize=thread,vptr -fsanitize=address" with mask \c NeedsUbsanRt
128 /// would produce "-fsanitize=vptr".
129 static std::string
lastArgumentForMask(const Driver
&D
,
130 const llvm::opt::ArgList
&Args
,
133 /// Produce an argument string from argument \p A, which shows how it provides
134 /// a value in \p Mask. For instance, the argument
135 /// "-fsanitize=address,alignment" with mask \c NeedsUbsanRt would produce
136 /// "-fsanitize=alignment".
137 static std::string
describeSanitizeArg(const llvm::opt::Arg
*A
,
140 /// Produce a string containing comma-separated names of sanitizers in \p
142 static std::string
toString(const clang::SanitizerSet
&Sanitizers
);
144 /// Return true if an execute-only target disallows data access to code
146 static bool isExecuteOnlyTarget(const llvm::Triple
&Triple
,
147 const llvm::opt::ArgList
&Args
) {
150 return Args
.hasFlagNoClaim(options::OPT_mexecute_only
,
151 options::OPT_mno_execute_only
, false);
154 static void validateSpecialCaseListFormat(const Driver
&D
,
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
;
168 static void addDefaultIgnorelists(const Driver
&D
, SanitizerMask Kinds
,
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
))
190 clang::SmallString
<64> Path(D
.ResourceDir
);
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
)
195 // If cfi_ignorelist.txt cannot be found in the resource dir, driver
197 D
.Diag(clang::diag::err_drv_missing_sanitizer_ignorelist
) << Path
;
199 validateSpecialCaseListFormat(
200 D
, IgnorelistFiles
, clang::diag::err_drv_malformed_sanitizer_ignorelist
,
204 /// Parse -f(no-)?sanitize-(coverage-)?(allow|ignore)list argument's values,
205 /// diagnosing any invalid file paths and validating special case list format.
206 static void parseSpecialCaseListArg(const Driver
&D
,
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
) {
214 // Match -fsanitize-(coverage-)?(allow|ignore)list.
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
;
223 // Match -fno-sanitize-ignorelist.
224 } else if (Arg
->getOption().matches(NoSCLOptionID
)) {
229 validateSpecialCaseListFormat(D
, SCLFiles
, MalformedSCLErrorDiagID
,
233 /// Sets group bits for every group that has at least one representative already
234 /// enabled in \p Kinds.
235 static SanitizerMask
setGroupBits(SanitizerMask Kinds
) {
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"
244 static SanitizerMask
parseSanitizeTrapArgs(const Driver
&D
,
245 const llvm::opt::ArgList
&Args
,
246 bool DiagnoseErrors
) {
247 SanitizerMask TrapRemove
; // During the loop below, the accumulated set of
248 // sanitizers disabled by the current sanitizer
249 // argument or any argument after it.
250 SanitizerMask TrappingKinds
;
251 SanitizerMask TrappingSupportedWithGroups
= setGroupBits(TrappingSupported
);
253 for (const llvm::opt::Arg
*Arg
: llvm::reverse(Args
)) {
254 if (Arg
->getOption().matches(options::OPT_fsanitize_trap_EQ
)) {
256 SanitizerMask Add
= parseArgValues(D
, Arg
, true);
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
);
265 TrappingKinds
|= expandSanitizerGroups(Add
) & ~TrapRemove
;
266 } else if (Arg
->getOption().matches(options::OPT_fno_sanitize_trap_EQ
)) {
269 expandSanitizerGroups(parseArgValues(D
, Arg
, DiagnoseErrors
));
273 // Apply default trapping behavior.
274 TrappingKinds
|= TrappingDefault
& ~TrapRemove
;
276 return TrappingKinds
;
279 bool SanitizerArgs::needsFuzzerInterceptors() const {
280 return needsFuzzer() && !needsAsanRt() && !needsTsanRt() && !needsMsanRt();
283 bool SanitizerArgs::needsUbsanRt() const {
284 // All of these include ubsan.
285 if (needsAsanRt() || needsMsanRt() || needsHwasanRt() || needsTsanRt() ||
286 needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() ||
287 (needsScudoRt() && !requiresMinimalRuntime()))
290 return (Sanitizers
.Mask
& NeedsUbsanRt
& ~TrapSanitizers
.Mask
) ||
294 bool SanitizerArgs::needsCfiRt() const {
295 return !(Sanitizers
.Mask
& SanitizerKind::CFI
& ~TrapSanitizers
.Mask
) &&
296 CfiCrossDso
&& !ImplicitCfiRuntime
;
299 bool SanitizerArgs::needsCfiDiagRt() const {
300 return (Sanitizers
.Mask
& SanitizerKind::CFI
& ~TrapSanitizers
.Mask
) &&
301 CfiCrossDso
&& !ImplicitCfiRuntime
;
304 bool SanitizerArgs::requiresPIE() const { return NeedPIE
; }
306 bool SanitizerArgs::needsUnwindTables() const {
307 return static_cast<bool>(Sanitizers
.Mask
& NeedsUnwindTables
);
310 bool SanitizerArgs::needsLTO() const {
311 return static_cast<bool>(Sanitizers
.Mask
& NeedsLTO
);
314 SanitizerArgs::SanitizerArgs(const ToolChain
&TC
,
315 const llvm::opt::ArgList
&Args
,
316 bool DiagnoseErrors
) {
317 SanitizerMask AllRemove
; // During the loop below, the accumulated set of
318 // sanitizers disabled by the current sanitizer
319 // argument or any argument after it.
320 SanitizerMask AllAddedKinds
; // Mask of all sanitizers ever enabled by
321 // -fsanitize= flags (directly or via group
322 // expansion), some of which may be disabled
323 // later. Used to carefully prune
324 // unused-argument diagnostics.
325 SanitizerMask DiagnosedKinds
; // All Kinds we have diagnosed up to now.
326 // Used to deduplicate diagnostics.
328 const SanitizerMask Supported
= setGroupBits(TC
.getSupportedSanitizers());
330 CfiCrossDso
= Args
.hasFlag(options::OPT_fsanitize_cfi_cross_dso
,
331 options::OPT_fno_sanitize_cfi_cross_dso
, false);
333 ToolChain::RTTIMode RTTIMode
= TC
.getRTTIMode();
335 const Driver
&D
= TC
.getDriver();
336 SanitizerMask TrappingKinds
= parseSanitizeTrapArgs(D
, Args
, DiagnoseErrors
);
337 SanitizerMask InvalidTrappingKinds
= TrappingKinds
& NotAllowedWithTrap
;
340 Args
.hasFlag(options::OPT_fsanitize_minimal_runtime
,
341 options::OPT_fno_sanitize_minimal_runtime
, MinimalRuntime
);
343 // The object size sanitizer should not be enabled at -O0.
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
)) {
351 SanitizerMask Add
= parseArgValues(D
, Arg
, DiagnoseErrors
);
353 if (RemoveObjectSizeAtO0
) {
354 AllRemove
|= SanitizerKind::ObjectSize
;
356 // The user explicitly enabled the object size sanitizer. Warn
357 // that this does nothing at -O0.
358 if ((Add
& SanitizerKind::ObjectSize
) && DiagnoseErrors
)
359 D
.Diag(diag::warn_drv_object_size_disabled_O0
)
360 << Arg
->getAsString(Args
);
363 AllAddedKinds
|= expandSanitizerGroups(Add
);
365 // Avoid diagnosing any sanitizer which is disabled later.
367 // At this point we have not expanded groups, so any unsupported
368 // sanitizers in Add are those which have been explicitly enabled.
370 if (SanitizerMask KindsToDiagnose
=
371 Add
& InvalidTrappingKinds
& ~DiagnosedKinds
) {
372 if (DiagnoseErrors
) {
373 std::string Desc
= describeSanitizeArg(Arg
, KindsToDiagnose
);
374 D
.Diag(diag::err_drv_argument_not_allowed_with
)
375 << Desc
<< "-fsanitize-trap=undefined";
377 DiagnosedKinds
|= KindsToDiagnose
;
379 Add
&= ~InvalidTrappingKinds
;
381 if (MinimalRuntime
) {
382 if (SanitizerMask KindsToDiagnose
=
383 Add
& NotAllowedWithMinimalRuntime
& ~DiagnosedKinds
) {
384 if (DiagnoseErrors
) {
385 std::string Desc
= describeSanitizeArg(Arg
, KindsToDiagnose
);
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"
402 Add
&= ~SanitizerKind::Function
;
403 DiagnosedKinds
|= SanitizerKind::Function
;
406 // -fsanitize=function and -fsanitize=kcfi instrument indirect function
407 // calls to load a type hash before the function label. Therefore, an
408 // execute-only target doesn't support the function and kcfi sanitizers.
409 const llvm::Triple
&Triple
= TC
.getTriple();
410 if (isExecuteOnlyTarget(Triple
, Args
)) {
411 if (SanitizerMask KindsToDiagnose
=
412 Add
& NotAllowedWithExecuteOnly
& ~DiagnosedKinds
) {
413 if (DiagnoseErrors
) {
414 std::string Desc
= describeSanitizeArg(Arg
, KindsToDiagnose
);
415 D
.Diag(diag::err_drv_argument_not_allowed_with
)
416 << Desc
<< Triple
.str();
418 DiagnosedKinds
|= KindsToDiagnose
;
420 Add
&= ~NotAllowedWithExecuteOnly
;
423 // FIXME: Make CFI on member function calls compatible with cross-DSO CFI.
424 // There are currently two problems:
425 // - Virtual function call checks need to pass a pointer to the function
426 // address to llvm.type.test and a pointer to the address point to the
427 // diagnostic function. Currently we pass the same pointer to both
429 // - Non-virtual function call checks may need to check multiple type
431 // Fixing both of those may require changes to the cross-DSO CFI
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";
438 Add
&= ~SanitizerKind::CFIMFCall
;
439 DiagnosedKinds
|= SanitizerKind::CFIMFCall
;
442 if (SanitizerMask KindsToDiagnose
= Add
& ~Supported
& ~DiagnosedKinds
) {
443 if (DiagnoseErrors
) {
444 std::string Desc
= describeSanitizeArg(Arg
, KindsToDiagnose
);
445 D
.Diag(diag::err_drv_unsupported_opt_for_target
)
446 << Desc
<< TC
.getTriple().str();
448 DiagnosedKinds
|= KindsToDiagnose
;
452 // Test for -fno-rtti + explicit -fsanitizer=vptr before expanding groups
453 // so we don't error out if -fno-rtti and -fsanitize=undefined were
455 if ((Add
& SanitizerKind::Vptr
) && (RTTIMode
== ToolChain::RM_Disabled
)) {
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?");
459 // The user explicitly passed -fno-rtti with -fsanitize=vptr, but
460 // the vptr sanitizer requires RTTI, so this is a user error.
462 D
.Diag(diag::err_drv_argument_not_allowed_with
)
463 << "-fsanitize=vptr" << NoRTTIArg
->getAsString(Args
);
465 // The vptr sanitizer requires RTTI, but RTTI is disabled (by
466 // default). Warn that the vptr sanitizer is being disabled.
468 D
.Diag(diag::warn_drv_disabling_vptr_no_rtti_default
);
471 // Take out the Vptr sanitizer from the enabled sanitizers
472 AllRemove
|= SanitizerKind::Vptr
;
475 Add
= expandSanitizerGroups(Add
);
476 // Group expansion may have enabled a sanitizer which is disabled later.
478 // Silently discard any unsupported sanitizers implicitly enabled through
480 Add
&= ~InvalidTrappingKinds
;
481 if (MinimalRuntime
) {
482 Add
&= ~NotAllowedWithMinimalRuntime
;
484 // NotAllowedWithExecuteOnly is silently discarded on an execute-only
485 // target if implicitly enabled through group expansion.
486 if (isExecuteOnlyTarget(Triple
, Args
))
487 Add
&= ~NotAllowedWithExecuteOnly
;
489 Add
&= ~SanitizerKind::CFIMFCall
;
492 if (Add
& SanitizerKind::Fuzzer
)
493 Add
|= SanitizerKind::FuzzerNoLink
;
495 // Enable coverage if the fuzzing flag is set.
496 if (Add
& SanitizerKind::FuzzerNoLink
) {
497 CoverageFeatures
|= CoverageInline8bitCounters
| CoverageIndirCall
|
498 CoverageTraceCmp
| CoveragePCTable
;
499 // Due to TLS differences, stack depth tracking is only enabled on Linux
500 if (TC
.getTriple().isOSLinux())
501 CoverageFeatures
|= CoverageStackDepth
;
505 } else if (Arg
->getOption().matches(options::OPT_fno_sanitize_EQ
)) {
507 SanitizerMask Remove
= parseArgValues(D
, Arg
, DiagnoseErrors
);
508 AllRemove
|= expandSanitizerGroups(Remove
);
512 std::pair
<SanitizerMask
, SanitizerMask
> IncompatibleGroups
[] = {
513 std::make_pair(SanitizerKind::Address
,
514 SanitizerKind::Thread
| SanitizerKind::Memory
),
515 std::make_pair(SanitizerKind::Thread
, SanitizerKind::Memory
),
516 std::make_pair(SanitizerKind::Leak
,
517 SanitizerKind::Thread
| SanitizerKind::Memory
),
518 std::make_pair(SanitizerKind::KernelAddress
,
519 SanitizerKind::Address
| SanitizerKind::Leak
|
520 SanitizerKind::Thread
| SanitizerKind::Memory
),
521 std::make_pair(SanitizerKind::HWAddress
,
522 SanitizerKind::Address
| SanitizerKind::Thread
|
523 SanitizerKind::Memory
| SanitizerKind::KernelAddress
),
524 std::make_pair(SanitizerKind::Scudo
,
525 SanitizerKind::Address
| SanitizerKind::HWAddress
|
526 SanitizerKind::Leak
| SanitizerKind::Thread
|
527 SanitizerKind::Memory
| SanitizerKind::KernelAddress
),
528 std::make_pair(SanitizerKind::SafeStack
,
529 (TC
.getTriple().isOSFuchsia() ? SanitizerMask()
530 : SanitizerKind::Leak
) |
531 SanitizerKind::Address
| SanitizerKind::HWAddress
|
532 SanitizerKind::Thread
| SanitizerKind::Memory
|
533 SanitizerKind::KernelAddress
),
534 std::make_pair(SanitizerKind::KernelHWAddress
,
535 SanitizerKind::Address
| SanitizerKind::HWAddress
|
536 SanitizerKind::Leak
| SanitizerKind::Thread
|
537 SanitizerKind::Memory
| SanitizerKind::KernelAddress
|
538 SanitizerKind::SafeStack
),
539 std::make_pair(SanitizerKind::KernelMemory
,
540 SanitizerKind::Address
| SanitizerKind::HWAddress
|
541 SanitizerKind::Leak
| SanitizerKind::Thread
|
542 SanitizerKind::Memory
| SanitizerKind::KernelAddress
|
543 SanitizerKind::Scudo
| SanitizerKind::SafeStack
),
544 std::make_pair(SanitizerKind::MemTag
,
545 SanitizerKind::Address
| SanitizerKind::KernelAddress
|
546 SanitizerKind::HWAddress
|
547 SanitizerKind::KernelHWAddress
),
548 std::make_pair(SanitizerKind::KCFI
, SanitizerKind::Function
)};
549 // Enable toolchain specific default sanitizers if not explicitly disabled.
550 SanitizerMask Default
= TC
.getDefaultSanitizers() & ~AllRemove
;
552 // Disable default sanitizers that are incompatible with explicitly requested
554 for (auto G
: IncompatibleGroups
) {
555 SanitizerMask Group
= G
.first
;
556 if ((Default
& Group
) && (Kinds
& G
.second
))
562 // We disable the vptr sanitizer if it was enabled by group expansion but RTTI
564 if ((Kinds
& SanitizerKind::Vptr
) && (RTTIMode
== ToolChain::RM_Disabled
)) {
565 Kinds
&= ~SanitizerKind::Vptr
;
568 // Check that LTO is enabled if we need it.
569 if ((Kinds
& NeedsLTO
) && !D
.isUsingLTO() && DiagnoseErrors
) {
570 D
.Diag(diag::err_drv_argument_only_allowed_with
)
571 << lastArgumentForMask(D
, Args
, Kinds
& NeedsLTO
) << "-flto";
574 if ((Kinds
& SanitizerKind::ShadowCallStack
) && TC
.getTriple().isAArch64() &&
575 !llvm::AArch64::isX18ReservedByDefault(TC
.getTriple()) &&
576 !Args
.hasArg(options::OPT_ffixed_x18
) && DiagnoseErrors
) {
577 D
.Diag(diag::err_drv_argument_only_allowed_with
)
578 << lastArgumentForMask(D
, Args
, Kinds
& SanitizerKind::ShadowCallStack
)
582 // Report error if there are non-trapping sanitizers that require
583 // c++abi-specific parts of UBSan runtime, and they are not provided by the
584 // toolchain. We don't have a good way to check the latter, so we just
585 // check if the toolchan supports vptr.
586 if (~Supported
& SanitizerKind::Vptr
) {
587 SanitizerMask KindsToDiagnose
= Kinds
& ~TrappingKinds
& NeedsUbsanCxxRt
;
588 // The runtime library supports the Microsoft C++ ABI, but only well enough
589 // for CFI. FIXME: Remove this once we support vptr on Windows.
590 if (TC
.getTriple().isOSWindows())
591 KindsToDiagnose
&= ~SanitizerKind::CFI
;
592 if (KindsToDiagnose
) {
594 S
.Mask
= KindsToDiagnose
;
596 D
.Diag(diag::err_drv_unsupported_opt_for_target
)
597 << ("-fno-sanitize-trap=" + toString(S
)) << TC
.getTriple().str();
598 Kinds
&= ~KindsToDiagnose
;
602 // Warn about incompatible groups of sanitizers.
603 for (auto G
: IncompatibleGroups
) {
604 SanitizerMask Group
= G
.first
;
606 if (SanitizerMask Incompatible
= Kinds
& G
.second
) {
608 D
.Diag(clang::diag::err_drv_argument_not_allowed_with
)
609 << lastArgumentForMask(D
, Args
, Group
)
610 << lastArgumentForMask(D
, Args
, Incompatible
);
611 Kinds
&= ~Incompatible
;
615 // FIXME: Currently -fsanitize=leak is silently ignored in the presence of
616 // -fsanitize=address. Perhaps it should print an error, or perhaps
617 // -f(-no)sanitize=leak should change whether leak detection is enabled by
620 // Parse -f(no-)?sanitize-recover flags.
621 SanitizerMask RecoverableKinds
= RecoverableByDefault
| AlwaysRecoverable
;
622 SanitizerMask DiagnosedUnrecoverableKinds
;
623 SanitizerMask DiagnosedAlwaysRecoverableKinds
;
624 for (const auto *Arg
: Args
) {
625 if (Arg
->getOption().matches(options::OPT_fsanitize_recover_EQ
)) {
626 SanitizerMask Add
= parseArgValues(D
, Arg
, DiagnoseErrors
);
627 // Report error if user explicitly tries to recover from unrecoverable
629 if (SanitizerMask KindsToDiagnose
=
630 Add
& Unrecoverable
& ~DiagnosedUnrecoverableKinds
) {
631 SanitizerSet SetToDiagnose
;
632 SetToDiagnose
.Mask
|= KindsToDiagnose
;
634 D
.Diag(diag::err_drv_unsupported_option_argument
)
635 << Arg
->getSpelling() << toString(SetToDiagnose
);
636 DiagnosedUnrecoverableKinds
|= KindsToDiagnose
;
638 RecoverableKinds
|= expandSanitizerGroups(Add
);
640 } else if (Arg
->getOption().matches(options::OPT_fno_sanitize_recover_EQ
)) {
641 SanitizerMask Remove
= parseArgValues(D
, Arg
, DiagnoseErrors
);
642 // Report error if user explicitly tries to disable recovery from
643 // always recoverable sanitizer.
644 if (SanitizerMask KindsToDiagnose
=
645 Remove
& AlwaysRecoverable
& ~DiagnosedAlwaysRecoverableKinds
) {
646 SanitizerSet SetToDiagnose
;
647 SetToDiagnose
.Mask
|= KindsToDiagnose
;
649 D
.Diag(diag::err_drv_unsupported_option_argument
)
650 << Arg
->getSpelling() << toString(SetToDiagnose
);
651 DiagnosedAlwaysRecoverableKinds
|= KindsToDiagnose
;
653 RecoverableKinds
&= ~expandSanitizerGroups(Remove
);
657 RecoverableKinds
&= Kinds
;
658 RecoverableKinds
&= ~Unrecoverable
;
660 TrappingKinds
&= Kinds
;
661 RecoverableKinds
&= ~TrappingKinds
;
663 // Setup ignorelist files.
664 // Add default ignorelist from resource directory for activated sanitizers,
665 // and validate special case lists format.
666 if (!Args
.hasArgNoClaim(options::OPT_fno_sanitize_ignorelist
))
667 addDefaultIgnorelists(D
, Kinds
, SystemIgnorelistFiles
, DiagnoseErrors
);
669 // Parse -f(no-)?sanitize-ignorelist options.
670 // This also validates special case lists format.
671 parseSpecialCaseListArg(
672 D
, Args
, UserIgnorelistFiles
, options::OPT_fsanitize_ignorelist_EQ
,
673 options::OPT_fno_sanitize_ignorelist
,
674 clang::diag::err_drv_malformed_sanitizer_ignorelist
, DiagnoseErrors
);
676 // Parse -f[no-]sanitize-memory-track-origins[=level] options.
677 if (AllAddedKinds
& SanitizerKind::Memory
) {
679 Args
.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ
,
680 options::OPT_fno_sanitize_memory_track_origins
)) {
681 if (!A
->getOption().matches(
682 options::OPT_fno_sanitize_memory_track_origins
)) {
683 StringRef S
= A
->getValue();
684 if (S
.getAsInteger(0, MsanTrackOrigins
) || MsanTrackOrigins
< 0 ||
685 MsanTrackOrigins
> 2) {
687 D
.Diag(clang::diag::err_drv_invalid_value
)
688 << A
->getAsString(Args
) << S
;
692 MsanUseAfterDtor
= Args
.hasFlag(
693 options::OPT_fsanitize_memory_use_after_dtor
,
694 options::OPT_fno_sanitize_memory_use_after_dtor
, MsanUseAfterDtor
);
695 MsanParamRetval
= Args
.hasFlag(
696 options::OPT_fsanitize_memory_param_retval
,
697 options::OPT_fno_sanitize_memory_param_retval
, MsanParamRetval
);
698 } else if (AllAddedKinds
& SanitizerKind::KernelMemory
) {
699 MsanUseAfterDtor
= false;
700 MsanParamRetval
= Args
.hasFlag(
701 options::OPT_fsanitize_memory_param_retval
,
702 options::OPT_fno_sanitize_memory_param_retval
, MsanParamRetval
);
704 MsanUseAfterDtor
= false;
705 MsanParamRetval
= false;
708 if (AllAddedKinds
& SanitizerKind::MemTag
) {
710 Args
.getLastArgValue(options::OPT_fsanitize_memtag_mode_EQ
, "sync");
711 if (S
== "async" || S
== "sync") {
712 MemtagMode
= S
.str();
714 D
.Diag(clang::diag::err_drv_invalid_value_with_suggestion
)
715 << "-fsanitize-memtag-mode=" << S
<< "{async, sync}";
720 if (AllAddedKinds
& SanitizerKind::Thread
) {
721 TsanMemoryAccess
= Args
.hasFlag(
722 options::OPT_fsanitize_thread_memory_access
,
723 options::OPT_fno_sanitize_thread_memory_access
, TsanMemoryAccess
);
724 TsanFuncEntryExit
= Args
.hasFlag(
725 options::OPT_fsanitize_thread_func_entry_exit
,
726 options::OPT_fno_sanitize_thread_func_entry_exit
, TsanFuncEntryExit
);
728 Args
.hasFlag(options::OPT_fsanitize_thread_atomics
,
729 options::OPT_fno_sanitize_thread_atomics
, TsanAtomics
);
732 if (AllAddedKinds
& SanitizerKind::CFI
) {
733 // Without PIE, external function address may resolve to a PLT record, which
734 // can not be verified by the target module.
735 NeedPIE
|= CfiCrossDso
;
736 CfiICallGeneralizePointers
=
737 Args
.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers
);
739 CfiICallNormalizeIntegers
=
740 Args
.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers
);
742 if (CfiCrossDso
&& CfiICallGeneralizePointers
&& DiagnoseErrors
)
743 D
.Diag(diag::err_drv_argument_not_allowed_with
)
744 << "-fsanitize-cfi-cross-dso"
745 << "-fsanitize-cfi-icall-generalize-pointers";
747 CfiCanonicalJumpTables
=
748 Args
.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables
,
749 options::OPT_fno_sanitize_cfi_canonical_jump_tables
, true);
752 if (AllAddedKinds
& SanitizerKind::KCFI
) {
753 CfiICallNormalizeIntegers
=
754 Args
.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers
);
756 if (AllAddedKinds
& SanitizerKind::CFI
&& DiagnoseErrors
)
757 D
.Diag(diag::err_drv_argument_not_allowed_with
)
759 << lastArgumentForMask(D
, Args
, SanitizerKind::CFI
);
762 Stats
= Args
.hasFlag(options::OPT_fsanitize_stats
,
763 options::OPT_fno_sanitize_stats
, false);
765 if (MinimalRuntime
) {
766 SanitizerMask IncompatibleMask
=
767 Kinds
& ~setGroupBits(CompatibleWithMinimalRuntime
);
768 if (IncompatibleMask
&& DiagnoseErrors
)
769 D
.Diag(clang::diag::err_drv_argument_not_allowed_with
)
770 << "-fsanitize-minimal-runtime"
771 << lastArgumentForMask(D
, Args
, IncompatibleMask
);
773 SanitizerMask NonTrappingCfi
= Kinds
& SanitizerKind::CFI
& ~TrappingKinds
;
774 if (NonTrappingCfi
&& DiagnoseErrors
)
775 D
.Diag(clang::diag::err_drv_argument_only_allowed_with
)
776 << "fsanitize-minimal-runtime"
777 << "fsanitize-trap=cfi";
780 // Parse -f(no-)?sanitize-coverage flags if coverage is supported by the
781 // enabled sanitizers.
782 for (const auto *Arg
: Args
) {
783 if (Arg
->getOption().matches(options::OPT_fsanitize_coverage
)) {
784 int LegacySanitizeCoverage
;
785 if (Arg
->getNumValues() == 1 &&
786 !StringRef(Arg
->getValue(0))
787 .getAsInteger(0, LegacySanitizeCoverage
)) {
788 CoverageFeatures
= 0;
790 if (LegacySanitizeCoverage
!= 0 && DiagnoseErrors
) {
791 D
.Diag(diag::warn_drv_deprecated_arg
)
792 << Arg
->getAsString(Args
) << "-fsanitize-coverage=trace-pc-guard";
796 CoverageFeatures
|= parseCoverageFeatures(D
, Arg
, DiagnoseErrors
);
798 // Disable coverage and not claim the flags if there is at least one
799 // non-supporting sanitizer.
800 if (!(AllAddedKinds
& ~AllRemove
& ~setGroupBits(SupportsCoverage
))) {
803 CoverageFeatures
= 0;
805 } else if (Arg
->getOption().matches(options::OPT_fno_sanitize_coverage
)) {
807 CoverageFeatures
&= ~parseCoverageFeatures(D
, Arg
, DiagnoseErrors
);
810 // Choose at most one coverage type: function, bb, or edge.
811 if (DiagnoseErrors
) {
812 if ((CoverageFeatures
& CoverageFunc
) && (CoverageFeatures
& CoverageBB
))
813 D
.Diag(clang::diag::err_drv_argument_not_allowed_with
)
814 << "-fsanitize-coverage=func"
815 << "-fsanitize-coverage=bb";
816 if ((CoverageFeatures
& CoverageFunc
) && (CoverageFeatures
& CoverageEdge
))
817 D
.Diag(clang::diag::err_drv_argument_not_allowed_with
)
818 << "-fsanitize-coverage=func"
819 << "-fsanitize-coverage=edge";
820 if ((CoverageFeatures
& CoverageBB
) && (CoverageFeatures
& CoverageEdge
))
821 D
.Diag(clang::diag::err_drv_argument_not_allowed_with
)
822 << "-fsanitize-coverage=bb"
823 << "-fsanitize-coverage=edge";
824 // Basic block tracing and 8-bit counters require some type of coverage
826 if (CoverageFeatures
& CoverageTraceBB
)
827 D
.Diag(clang::diag::warn_drv_deprecated_arg
)
828 << "-fsanitize-coverage=trace-bb"
829 << "-fsanitize-coverage=trace-pc-guard";
830 if (CoverageFeatures
& Coverage8bitCounters
)
831 D
.Diag(clang::diag::warn_drv_deprecated_arg
)
832 << "-fsanitize-coverage=8bit-counters"
833 << "-fsanitize-coverage=trace-pc-guard";
836 int InsertionPointTypes
= CoverageFunc
| CoverageBB
| CoverageEdge
;
837 int InstrumentationTypes
= CoverageTracePC
| CoverageTracePCGuard
|
838 CoverageInline8bitCounters
| CoverageTraceLoads
|
839 CoverageTraceStores
| CoverageInlineBoolFlag
|
841 if ((CoverageFeatures
& InsertionPointTypes
) &&
842 !(CoverageFeatures
& InstrumentationTypes
) && DiagnoseErrors
) {
843 D
.Diag(clang::diag::warn_drv_deprecated_arg
)
844 << "-fsanitize-coverage=[func|bb|edge]"
845 << "-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc],["
849 // trace-pc w/o func/bb/edge implies edge.
850 if (!(CoverageFeatures
& InsertionPointTypes
)) {
851 if (CoverageFeatures
&
852 (CoverageTracePC
| CoverageTracePCGuard
| CoverageInline8bitCounters
|
853 CoverageInlineBoolFlag
| CoverageControlFlow
))
854 CoverageFeatures
|= CoverageEdge
;
856 if (CoverageFeatures
& CoverageStackDepth
)
857 CoverageFeatures
|= CoverageFunc
;
860 // Parse -fsanitize-coverage-(allow|ignore)list options if coverage enabled.
861 // This also validates special case lists format.
862 // Here, OptSpecifier() acts as a never-matching command-line argument.
863 // So, there is no way to clear coverage lists but you can append to them.
864 if (CoverageFeatures
) {
865 parseSpecialCaseListArg(
866 D
, Args
, CoverageAllowlistFiles
,
867 options::OPT_fsanitize_coverage_allowlist
, OptSpecifier(),
868 clang::diag::err_drv_malformed_sanitizer_coverage_allowlist
,
870 parseSpecialCaseListArg(
871 D
, Args
, CoverageIgnorelistFiles
,
872 options::OPT_fsanitize_coverage_ignorelist
, OptSpecifier(),
873 clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist
,
877 // Parse -f(no-)?sanitize-metadata.
878 for (const auto *Arg
:
879 Args
.filtered(options::OPT_fexperimental_sanitize_metadata_EQ
,
880 options::OPT_fno_experimental_sanitize_metadata_EQ
)) {
881 if (Arg
->getOption().matches(
882 options::OPT_fexperimental_sanitize_metadata_EQ
)) {
884 BinaryMetadataFeatures
|=
885 parseBinaryMetadataFeatures(D
, Arg
, DiagnoseErrors
);
888 BinaryMetadataFeatures
&=
889 ~parseBinaryMetadataFeatures(D
, Arg
, DiagnoseErrors
);
893 // Parse -fsanitize-metadata-ignorelist option if enabled.
894 if (BinaryMetadataFeatures
) {
895 parseSpecialCaseListArg(
896 D
, Args
, BinaryMetadataIgnorelistFiles
,
897 options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ
,
898 OptSpecifier(), // Cannot clear ignore list, only append.
899 clang::diag::err_drv_malformed_sanitizer_metadata_ignorelist
,
904 Args
.hasFlag(options::OPT_shared_libsan
, options::OPT_static_libsan
,
905 TC
.getTriple().isAndroid() || TC
.getTriple().isOSFuchsia() ||
906 TC
.getTriple().isOSDarwin());
908 ImplicitCfiRuntime
= TC
.getTriple().isAndroid();
910 if (AllAddedKinds
& SanitizerKind::Address
) {
911 NeedPIE
|= TC
.getTriple().isOSFuchsia();
913 Args
.getLastArg(options::OPT_fsanitize_address_field_padding
)) {
914 StringRef S
= A
->getValue();
915 // Legal values are 0 and 1, 2, but in future we may add more levels.
916 if ((S
.getAsInteger(0, AsanFieldPadding
) || AsanFieldPadding
< 0 ||
917 AsanFieldPadding
> 2) &&
919 D
.Diag(clang::diag::err_drv_invalid_value
) << A
->getAsString(Args
) << S
;
923 if (Arg
*WindowsDebugRTArg
=
924 Args
.getLastArg(options::OPT__SLASH_MTd
, options::OPT__SLASH_MT
,
925 options::OPT__SLASH_MDd
, options::OPT__SLASH_MD
,
926 options::OPT__SLASH_LDd
, options::OPT__SLASH_LD
)) {
927 switch (WindowsDebugRTArg
->getOption().getID()) {
928 case options::OPT__SLASH_MTd
:
929 case options::OPT__SLASH_MDd
:
930 case options::OPT__SLASH_LDd
:
931 if (DiagnoseErrors
) {
932 D
.Diag(clang::diag::err_drv_argument_not_allowed_with
)
933 << WindowsDebugRTArg
->getAsString(Args
)
934 << lastArgumentForMask(D
, Args
, SanitizerKind::Address
);
935 D
.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime
);
940 StableABI
= Args
.hasFlag(options::OPT_fsanitize_stable_abi
,
941 options::OPT_fno_sanitize_stable_abi
, false);
943 AsanUseAfterScope
= Args
.hasFlag(
944 options::OPT_fsanitize_address_use_after_scope
,
945 options::OPT_fno_sanitize_address_use_after_scope
, AsanUseAfterScope
);
947 AsanPoisonCustomArrayCookie
= Args
.hasFlag(
948 options::OPT_fsanitize_address_poison_custom_array_cookie
,
949 options::OPT_fno_sanitize_address_poison_custom_array_cookie
,
950 AsanPoisonCustomArrayCookie
);
952 AsanOutlineInstrumentation
=
953 Args
.hasFlag(options::OPT_fsanitize_address_outline_instrumentation
,
954 options::OPT_fno_sanitize_address_outline_instrumentation
,
955 AsanOutlineInstrumentation
);
957 AsanGlobalsDeadStripping
= Args
.hasFlag(
958 options::OPT_fsanitize_address_globals_dead_stripping
,
959 options::OPT_fno_sanitize_address_globals_dead_stripping
, true);
961 // Enable ODR indicators which allow better handling of mixed instrumented
962 // and uninstrumented globals. Disable them for Windows where weak odr
963 // indicators (.weak.__odr_asan_gen*) may cause multiple definition linker
964 // errors in the absence of -lldmingw.
965 AsanUseOdrIndicator
=
966 Args
.hasFlag(options::OPT_fsanitize_address_use_odr_indicator
,
967 options::OPT_fno_sanitize_address_use_odr_indicator
,
968 !TC
.getTriple().isOSWindows());
970 if (AllAddedKinds
& SanitizerKind::PointerCompare
& ~AllRemove
) {
971 AsanInvalidPointerCmp
= true;
974 if (AllAddedKinds
& SanitizerKind::PointerSubtract
& ~AllRemove
) {
975 AsanInvalidPointerSub
= true;
978 if (TC
.getTriple().isOSDarwin() &&
979 (Args
.hasArg(options::OPT_mkernel
) ||
980 Args
.hasArg(options::OPT_fapple_kext
))) {
981 AsanDtorKind
= llvm::AsanDtorKind::None
;
984 if (const auto *Arg
=
985 Args
.getLastArg(options::OPT_sanitize_address_destructor_EQ
)) {
986 auto parsedAsanDtorKind
= AsanDtorKindFromString(Arg
->getValue());
987 if (parsedAsanDtorKind
== llvm::AsanDtorKind::Invalid
&& DiagnoseErrors
) {
988 TC
.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument
)
989 << Arg
->getSpelling() << Arg
->getValue();
991 AsanDtorKind
= parsedAsanDtorKind
;
994 if (const auto *Arg
= Args
.getLastArg(
995 options::OPT_sanitize_address_use_after_return_EQ
)) {
996 auto parsedAsanUseAfterReturn
=
997 AsanDetectStackUseAfterReturnModeFromString(Arg
->getValue());
998 if (parsedAsanUseAfterReturn
==
999 llvm::AsanDetectStackUseAfterReturnMode::Invalid
&&
1001 TC
.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument
)
1002 << Arg
->getSpelling() << Arg
->getValue();
1004 AsanUseAfterReturn
= parsedAsanUseAfterReturn
;
1008 AsanUseAfterScope
= false;
1009 // -fsanitize=pointer-compare/pointer-subtract requires -fsanitize=address.
1010 SanitizerMask DetectInvalidPointerPairs
=
1011 SanitizerKind::PointerCompare
| SanitizerKind::PointerSubtract
;
1012 if ((AllAddedKinds
& DetectInvalidPointerPairs
& ~AllRemove
) &&
1014 TC
.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with
)
1015 << lastArgumentForMask(D
, Args
,
1016 SanitizerKind::PointerCompare
|
1017 SanitizerKind::PointerSubtract
)
1018 << "-fsanitize=address";
1022 if (AllAddedKinds
& SanitizerKind::HWAddress
) {
1023 if (Arg
*HwasanAbiArg
=
1024 Args
.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ
)) {
1025 HwasanAbi
= HwasanAbiArg
->getValue();
1026 if (HwasanAbi
!= "platform" && HwasanAbi
!= "interceptor" &&
1028 D
.Diag(clang::diag::err_drv_invalid_value
)
1029 << HwasanAbiArg
->getAsString(Args
) << HwasanAbi
;
1031 HwasanAbi
= "interceptor";
1033 if (TC
.getTriple().getArch() == llvm::Triple::x86_64
)
1034 HwasanUseAliases
= Args
.hasFlag(
1035 options::OPT_fsanitize_hwaddress_experimental_aliasing
,
1036 options::OPT_fno_sanitize_hwaddress_experimental_aliasing
,
1040 if (AllAddedKinds
& SanitizerKind::SafeStack
) {
1041 // SafeStack runtime is built into the system on Android and Fuchsia.
1043 !TC
.getTriple().isAndroid() && !TC
.getTriple().isOSFuchsia();
1047 Args
.hasFlag(options::OPT_fsanitize_link_runtime
,
1048 options::OPT_fno_sanitize_link_runtime
, LinkRuntimes
);
1050 // Parse -link-cxx-sanitizer flag.
1051 LinkCXXRuntimes
= Args
.hasArg(options::OPT_fsanitize_link_cxx_runtime
,
1052 options::OPT_fno_sanitize_link_cxx_runtime
,
1056 NeedsMemProfRt
= Args
.hasFlag(options::OPT_fmemory_profile
,
1057 options::OPT_fmemory_profile_EQ
,
1058 options::OPT_fno_memory_profile
, false);
1060 // Finally, initialize the set of available and recoverable sanitizers.
1061 Sanitizers
.Mask
|= Kinds
;
1062 RecoverableSanitizers
.Mask
|= RecoverableKinds
;
1063 TrapSanitizers
.Mask
|= TrappingKinds
;
1064 assert(!(RecoverableKinds
& TrappingKinds
) &&
1065 "Overlap between recoverable and trapping sanitizers");
1068 static std::string
toString(const clang::SanitizerSet
&Sanitizers
) {
1070 #define SANITIZER(NAME, ID) \
1071 if (Sanitizers.has(SanitizerKind::ID)) { \
1076 #include "clang/Basic/Sanitizers.def"
1080 static void addSpecialCaseListOpt(const llvm::opt::ArgList
&Args
,
1081 llvm::opt::ArgStringList
&CmdArgs
,
1082 const char *SCLOptFlag
,
1083 const std::vector
<std::string
> &SCLFiles
) {
1084 for (const auto &SCLPath
: SCLFiles
) {
1085 SmallString
<64> SCLOpt(SCLOptFlag
);
1087 CmdArgs
.push_back(Args
.MakeArgString(SCLOpt
));
1091 static void addIncludeLinkerOption(const ToolChain
&TC
,
1092 const llvm::opt::ArgList
&Args
,
1093 llvm::opt::ArgStringList
&CmdArgs
,
1094 StringRef SymbolName
) {
1095 SmallString
<64> LinkerOptionFlag
;
1096 LinkerOptionFlag
= "--linker-option=/include:";
1097 if (TC
.getTriple().getArch() == llvm::Triple::x86
) {
1098 // Win32 mangles C function names with a '_' prefix.
1099 LinkerOptionFlag
+= '_';
1101 LinkerOptionFlag
+= SymbolName
;
1102 CmdArgs
.push_back(Args
.MakeArgString(LinkerOptionFlag
));
1105 static bool hasTargetFeatureMTE(const llvm::opt::ArgStringList
&CmdArgs
) {
1106 for (auto Start
= CmdArgs
.begin(), End
= CmdArgs
.end(); Start
!= End
;
1108 auto It
= std::find(Start
, End
, StringRef("+mte"));
1111 if (It
> Start
&& *std::prev(It
) == StringRef("-target-feature"))
1118 void SanitizerArgs::addArgs(const ToolChain
&TC
, const llvm::opt::ArgList
&Args
,
1119 llvm::opt::ArgStringList
&CmdArgs
,
1120 types::ID InputType
) const {
1121 // NVPTX doesn't currently support sanitizers. Bailing out here means
1122 // that e.g. -fsanitize=address applies only to host code, which is what we
1124 if (TC
.getTriple().isNVPTX())
1126 // AMDGPU sanitizer support is experimental and controlled by -fgpu-sanitize.
1127 bool GPUSanitize
= false;
1128 if (TC
.getTriple().isAMDGPU()) {
1129 if (!Args
.hasFlag(options::OPT_fgpu_sanitize
, options::OPT_fno_gpu_sanitize
,
1135 // Translate available CoverageFeatures to corresponding clang-cc1 flags.
1136 // Do it even if Sanitizers.empty() since some forms of coverage don't require
1138 std::pair
<int, const char *> CoverageFlags
[] = {
1139 std::make_pair(CoverageFunc
, "-fsanitize-coverage-type=1"),
1140 std::make_pair(CoverageBB
, "-fsanitize-coverage-type=2"),
1141 std::make_pair(CoverageEdge
, "-fsanitize-coverage-type=3"),
1142 std::make_pair(CoverageIndirCall
, "-fsanitize-coverage-indirect-calls"),
1143 std::make_pair(CoverageTraceBB
, "-fsanitize-coverage-trace-bb"),
1144 std::make_pair(CoverageTraceCmp
, "-fsanitize-coverage-trace-cmp"),
1145 std::make_pair(CoverageTraceDiv
, "-fsanitize-coverage-trace-div"),
1146 std::make_pair(CoverageTraceGep
, "-fsanitize-coverage-trace-gep"),
1147 std::make_pair(Coverage8bitCounters
, "-fsanitize-coverage-8bit-counters"),
1148 std::make_pair(CoverageTracePC
, "-fsanitize-coverage-trace-pc"),
1149 std::make_pair(CoverageTracePCGuard
,
1150 "-fsanitize-coverage-trace-pc-guard"),
1151 std::make_pair(CoverageInline8bitCounters
,
1152 "-fsanitize-coverage-inline-8bit-counters"),
1153 std::make_pair(CoverageInlineBoolFlag
,
1154 "-fsanitize-coverage-inline-bool-flag"),
1155 std::make_pair(CoveragePCTable
, "-fsanitize-coverage-pc-table"),
1156 std::make_pair(CoverageNoPrune
, "-fsanitize-coverage-no-prune"),
1157 std::make_pair(CoverageStackDepth
, "-fsanitize-coverage-stack-depth"),
1158 std::make_pair(CoverageTraceLoads
, "-fsanitize-coverage-trace-loads"),
1159 std::make_pair(CoverageTraceStores
, "-fsanitize-coverage-trace-stores"),
1160 std::make_pair(CoverageControlFlow
, "-fsanitize-coverage-control-flow")};
1161 for (auto F
: CoverageFlags
) {
1162 if (CoverageFeatures
& F
.first
)
1163 CmdArgs
.push_back(F
.second
);
1165 addSpecialCaseListOpt(
1166 Args
, CmdArgs
, "-fsanitize-coverage-allowlist=", CoverageAllowlistFiles
);
1167 addSpecialCaseListOpt(Args
, CmdArgs
, "-fsanitize-coverage-ignorelist=",
1168 CoverageIgnorelistFiles
);
1171 // Translate available BinaryMetadataFeatures to corresponding clang-cc1
1172 // flags. Does not depend on any other sanitizers. Unsupported on GPUs.
1173 const std::pair
<int, std::string
> BinaryMetadataFlags
[] = {
1174 std::make_pair(BinaryMetadataCovered
, "covered"),
1175 std::make_pair(BinaryMetadataAtomics
, "atomics"),
1176 std::make_pair(BinaryMetadataUAR
, "uar")};
1177 for (const auto &F
: BinaryMetadataFlags
) {
1178 if (BinaryMetadataFeatures
& F
.first
)
1180 Args
.MakeArgString("-fexperimental-sanitize-metadata=" + F
.second
));
1182 addSpecialCaseListOpt(Args
, CmdArgs
,
1183 "-fexperimental-sanitize-metadata-ignorelist=",
1184 BinaryMetadataIgnorelistFiles
);
1187 if (TC
.getTriple().isOSWindows() && needsUbsanRt()) {
1188 // Instruct the code generator to embed linker directives in the object file
1189 // that cause the required runtime libraries to be linked.
1191 Args
.MakeArgString("--dependent-lib=" +
1192 TC
.getCompilerRTBasename(Args
, "ubsan_standalone")));
1193 if (types::isCXX(InputType
))
1194 CmdArgs
.push_back(Args
.MakeArgString(
1195 "--dependent-lib=" +
1196 TC
.getCompilerRTBasename(Args
, "ubsan_standalone_cxx")));
1198 if (TC
.getTriple().isOSWindows() && needsStatsRt()) {
1199 CmdArgs
.push_back(Args
.MakeArgString(
1200 "--dependent-lib=" + TC
.getCompilerRTBasename(Args
, "stats_client")));
1202 // The main executable must export the stats runtime.
1203 // FIXME: Only exporting from the main executable (e.g. based on whether the
1204 // translation unit defines main()) would save a little space, but having
1205 // multiple copies of the runtime shouldn't hurt.
1206 CmdArgs
.push_back(Args
.MakeArgString(
1207 "--dependent-lib=" + TC
.getCompilerRTBasename(Args
, "stats")));
1208 addIncludeLinkerOption(TC
, Args
, CmdArgs
, "__sanitizer_stats_register");
1211 if (Sanitizers
.empty())
1213 CmdArgs
.push_back(Args
.MakeArgString("-fsanitize=" + toString(Sanitizers
)));
1215 if (!RecoverableSanitizers
.empty())
1216 CmdArgs
.push_back(Args
.MakeArgString("-fsanitize-recover=" +
1217 toString(RecoverableSanitizers
)));
1219 if (!TrapSanitizers
.empty())
1221 Args
.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers
)));
1223 addSpecialCaseListOpt(Args
, CmdArgs
,
1224 "-fsanitize-ignorelist=", UserIgnorelistFiles
);
1225 addSpecialCaseListOpt(Args
, CmdArgs
,
1226 "-fsanitize-system-ignorelist=", SystemIgnorelistFiles
);
1228 if (MsanTrackOrigins
)
1229 CmdArgs
.push_back(Args
.MakeArgString("-fsanitize-memory-track-origins=" +
1230 Twine(MsanTrackOrigins
)));
1232 if (MsanUseAfterDtor
)
1233 CmdArgs
.push_back("-fsanitize-memory-use-after-dtor");
1235 if (!MsanParamRetval
)
1236 CmdArgs
.push_back("-fno-sanitize-memory-param-retval");
1238 // FIXME: Pass these parameters as function attributes, not as -llvm flags.
1239 if (!TsanMemoryAccess
) {
1240 CmdArgs
.push_back("-mllvm");
1241 CmdArgs
.push_back("-tsan-instrument-memory-accesses=0");
1242 CmdArgs
.push_back("-mllvm");
1243 CmdArgs
.push_back("-tsan-instrument-memintrinsics=0");
1245 if (!TsanFuncEntryExit
) {
1246 CmdArgs
.push_back("-mllvm");
1247 CmdArgs
.push_back("-tsan-instrument-func-entry-exit=0");
1250 CmdArgs
.push_back("-mllvm");
1251 CmdArgs
.push_back("-tsan-instrument-atomics=0");
1254 if (HwasanUseAliases
) {
1255 CmdArgs
.push_back("-mllvm");
1256 CmdArgs
.push_back("-hwasan-experimental-use-page-aliases=1");
1260 CmdArgs
.push_back("-fsanitize-cfi-cross-dso");
1262 if (CfiICallGeneralizePointers
)
1263 CmdArgs
.push_back("-fsanitize-cfi-icall-generalize-pointers");
1265 if (CfiICallNormalizeIntegers
)
1266 CmdArgs
.push_back("-fsanitize-cfi-icall-experimental-normalize-integers");
1268 if (CfiCanonicalJumpTables
)
1269 CmdArgs
.push_back("-fsanitize-cfi-canonical-jump-tables");
1272 CmdArgs
.push_back("-fsanitize-stats");
1275 CmdArgs
.push_back("-fsanitize-minimal-runtime");
1277 if (AsanFieldPadding
)
1278 CmdArgs
.push_back(Args
.MakeArgString("-fsanitize-address-field-padding=" +
1279 Twine(AsanFieldPadding
)));
1281 if (AsanUseAfterScope
)
1282 CmdArgs
.push_back("-fsanitize-address-use-after-scope");
1284 if (AsanPoisonCustomArrayCookie
)
1285 CmdArgs
.push_back("-fsanitize-address-poison-custom-array-cookie");
1287 if (AsanGlobalsDeadStripping
)
1288 CmdArgs
.push_back("-fsanitize-address-globals-dead-stripping");
1290 if (!AsanUseOdrIndicator
)
1291 CmdArgs
.push_back("-fno-sanitize-address-use-odr-indicator");
1293 if (AsanInvalidPointerCmp
) {
1294 CmdArgs
.push_back("-mllvm");
1295 CmdArgs
.push_back("-asan-detect-invalid-pointer-cmp");
1298 if (AsanInvalidPointerSub
) {
1299 CmdArgs
.push_back("-mllvm");
1300 CmdArgs
.push_back("-asan-detect-invalid-pointer-sub");
1303 if (AsanOutlineInstrumentation
) {
1304 CmdArgs
.push_back("-mllvm");
1305 CmdArgs
.push_back("-asan-instrumentation-with-call-threshold=0");
1308 // When emitting Stable ABI instrumentation, force outlining calls and avoid
1309 // inlining shadow memory poisoning. While this is a big performance burden
1310 // for now it allows full abstraction from implementation details.
1312 CmdArgs
.push_back("-mllvm");
1313 CmdArgs
.push_back("-asan-instrumentation-with-call-threshold=0");
1314 CmdArgs
.push_back("-mllvm");
1315 CmdArgs
.push_back("-asan-max-inline-poisoning-size=0");
1316 CmdArgs
.push_back("-mllvm");
1317 CmdArgs
.push_back("-asan-guard-against-version-mismatch=0");
1320 // Only pass the option to the frontend if the user requested,
1321 // otherwise the frontend will just use the codegen default.
1322 if (AsanDtorKind
!= llvm::AsanDtorKind::Invalid
) {
1323 CmdArgs
.push_back(Args
.MakeArgString("-fsanitize-address-destructor=" +
1324 AsanDtorKindToString(AsanDtorKind
)));
1327 if (AsanUseAfterReturn
!= llvm::AsanDetectStackUseAfterReturnMode::Invalid
) {
1328 CmdArgs
.push_back(Args
.MakeArgString(
1329 "-fsanitize-address-use-after-return=" +
1330 AsanDetectStackUseAfterReturnModeToString(AsanUseAfterReturn
)));
1333 if (!HwasanAbi
.empty()) {
1334 CmdArgs
.push_back("-default-function-attr");
1335 CmdArgs
.push_back(Args
.MakeArgString("hwasan-abi=" + HwasanAbi
));
1338 if (Sanitizers
.has(SanitizerKind::HWAddress
) && !HwasanUseAliases
) {
1339 CmdArgs
.push_back("-target-feature");
1340 CmdArgs
.push_back("+tagged-globals");
1343 // MSan: Workaround for PR16386.
1344 // ASan: This is mainly to help LSan with cases such as
1345 // https://github.com/google/sanitizers/issues/373
1346 // We can't make this conditional on -fsanitize=leak, as that flag shouldn't
1347 // affect compilation.
1348 if (Sanitizers
.has(SanitizerKind::Memory
) ||
1349 Sanitizers
.has(SanitizerKind::Address
))
1350 CmdArgs
.push_back("-fno-assume-sane-operator-new");
1352 // libFuzzer wants to intercept calls to certain library functions, so the
1353 // following -fno-builtin-* flags force the compiler to emit interposable
1354 // libcalls to these functions. Other sanitizers effectively do the same thing
1355 // by marking all library call sites with NoBuiltin attribute in their LLVM
1356 // pass. (see llvm::maybeMarkSanitizerLibraryCallNoBuiltin)
1357 if (Sanitizers
.has(SanitizerKind::FuzzerNoLink
)) {
1358 CmdArgs
.push_back("-fno-builtin-bcmp");
1359 CmdArgs
.push_back("-fno-builtin-memcmp");
1360 CmdArgs
.push_back("-fno-builtin-strncmp");
1361 CmdArgs
.push_back("-fno-builtin-strcmp");
1362 CmdArgs
.push_back("-fno-builtin-strncasecmp");
1363 CmdArgs
.push_back("-fno-builtin-strcasecmp");
1364 CmdArgs
.push_back("-fno-builtin-strstr");
1365 CmdArgs
.push_back("-fno-builtin-strcasestr");
1366 CmdArgs
.push_back("-fno-builtin-memmem");
1369 // Require -fvisibility= flag on non-Windows when compiling if vptr CFI is
1371 if (Sanitizers
.hasOneOf(CFIClasses
) && !TC
.getTriple().isOSWindows() &&
1372 !Args
.hasArg(options::OPT_fvisibility_EQ
)) {
1373 TC
.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with
)
1374 << lastArgumentForMask(TC
.getDriver(), Args
,
1375 Sanitizers
.Mask
& CFIClasses
)
1379 if (Sanitizers
.has(SanitizerKind::MemtagStack
) &&
1380 !hasTargetFeatureMTE(CmdArgs
))
1381 TC
.getDriver().Diag(diag::err_stack_tagging_requires_hardware_feature
);
1384 SanitizerMask
parseArgValues(const Driver
&D
, const llvm::opt::Arg
*A
,
1385 bool DiagnoseErrors
) {
1386 assert((A
->getOption().matches(options::OPT_fsanitize_EQ
) ||
1387 A
->getOption().matches(options::OPT_fno_sanitize_EQ
) ||
1388 A
->getOption().matches(options::OPT_fsanitize_recover_EQ
) ||
1389 A
->getOption().matches(options::OPT_fno_sanitize_recover_EQ
) ||
1390 A
->getOption().matches(options::OPT_fsanitize_trap_EQ
) ||
1391 A
->getOption().matches(options::OPT_fno_sanitize_trap_EQ
)) &&
1392 "Invalid argument in parseArgValues!");
1393 SanitizerMask Kinds
;
1394 for (int i
= 0, n
= A
->getNumValues(); i
!= n
; ++i
) {
1395 const char *Value
= A
->getValue(i
);
1397 // Special case: don't accept -fsanitize=all.
1398 if (A
->getOption().matches(options::OPT_fsanitize_EQ
) &&
1399 0 == strcmp("all", Value
))
1400 Kind
= SanitizerMask();
1402 Kind
= parseSanitizerValue(Value
, /*AllowGroups=*/true);
1406 else if (DiagnoseErrors
)
1407 D
.Diag(clang::diag::err_drv_unsupported_option_argument
)
1408 << A
->getSpelling() << Value
;
1413 int parseCoverageFeatures(const Driver
&D
, const llvm::opt::Arg
*A
,
1414 bool DiagnoseErrors
) {
1415 assert(A
->getOption().matches(options::OPT_fsanitize_coverage
) ||
1416 A
->getOption().matches(options::OPT_fno_sanitize_coverage
));
1418 for (int i
= 0, n
= A
->getNumValues(); i
!= n
; ++i
) {
1419 const char *Value
= A
->getValue(i
);
1420 int F
= llvm::StringSwitch
<int>(Value
)
1421 .Case("func", CoverageFunc
)
1422 .Case("bb", CoverageBB
)
1423 .Case("edge", CoverageEdge
)
1424 .Case("indirect-calls", CoverageIndirCall
)
1425 .Case("trace-bb", CoverageTraceBB
)
1426 .Case("trace-cmp", CoverageTraceCmp
)
1427 .Case("trace-div", CoverageTraceDiv
)
1428 .Case("trace-gep", CoverageTraceGep
)
1429 .Case("8bit-counters", Coverage8bitCounters
)
1430 .Case("trace-pc", CoverageTracePC
)
1431 .Case("trace-pc-guard", CoverageTracePCGuard
)
1432 .Case("no-prune", CoverageNoPrune
)
1433 .Case("inline-8bit-counters", CoverageInline8bitCounters
)
1434 .Case("inline-bool-flag", CoverageInlineBoolFlag
)
1435 .Case("pc-table", CoveragePCTable
)
1436 .Case("stack-depth", CoverageStackDepth
)
1437 .Case("trace-loads", CoverageTraceLoads
)
1438 .Case("trace-stores", CoverageTraceStores
)
1439 .Case("control-flow", CoverageControlFlow
)
1441 if (F
== 0 && DiagnoseErrors
)
1442 D
.Diag(clang::diag::err_drv_unsupported_option_argument
)
1443 << A
->getSpelling() << Value
;
1449 int parseBinaryMetadataFeatures(const Driver
&D
, const llvm::opt::Arg
*A
,
1450 bool DiagnoseErrors
) {
1452 A
->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ
) ||
1453 A
->getOption().matches(
1454 options::OPT_fno_experimental_sanitize_metadata_EQ
));
1456 for (int i
= 0, n
= A
->getNumValues(); i
!= n
; ++i
) {
1457 const char *Value
= A
->getValue(i
);
1458 int F
= llvm::StringSwitch
<int>(Value
)
1459 .Case("covered", BinaryMetadataCovered
)
1460 .Case("atomics", BinaryMetadataAtomics
)
1461 .Case("uar", BinaryMetadataUAR
)
1464 if (F
== 0 && DiagnoseErrors
)
1465 D
.Diag(clang::diag::err_drv_unsupported_option_argument
)
1466 << A
->getSpelling() << Value
;
1472 std::string
lastArgumentForMask(const Driver
&D
, const llvm::opt::ArgList
&Args
,
1473 SanitizerMask Mask
) {
1474 for (llvm::opt::ArgList::const_reverse_iterator I
= Args
.rbegin(),
1477 const auto *Arg
= *I
;
1478 if (Arg
->getOption().matches(options::OPT_fsanitize_EQ
)) {
1479 SanitizerMask AddKinds
=
1480 expandSanitizerGroups(parseArgValues(D
, Arg
, false));
1481 if (AddKinds
& Mask
)
1482 return describeSanitizeArg(Arg
, Mask
);
1483 } else if (Arg
->getOption().matches(options::OPT_fno_sanitize_EQ
)) {
1484 SanitizerMask RemoveKinds
=
1485 expandSanitizerGroups(parseArgValues(D
, Arg
, false));
1486 Mask
&= ~RemoveKinds
;
1489 llvm_unreachable("arg list didn't provide expected value");
1492 std::string
describeSanitizeArg(const llvm::opt::Arg
*A
, SanitizerMask Mask
) {
1493 assert(A
->getOption().matches(options::OPT_fsanitize_EQ
) &&
1494 "Invalid argument in describeSanitizerArg!");
1496 std::string Sanitizers
;
1497 for (int i
= 0, n
= A
->getNumValues(); i
!= n
; ++i
) {
1498 if (expandSanitizerGroups(
1499 parseSanitizerValue(A
->getValue(i
), /*AllowGroups=*/true)) &
1501 if (!Sanitizers
.empty())
1503 Sanitizers
+= A
->getValue(i
);
1507 assert(!Sanitizers
.empty() && "arg didn't provide expected value");
1508 return "-fsanitize=" + Sanitizers
;