clang 20.0.0git
SanitizerArgs.cpp
Go to the documentation of this file.
1//===--- SanitizerArgs.cpp - Arguments for sanitizer tools ---------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
10#include "clang/Driver/Driver.h"
13#include "llvm/ADT/StringRef.h"
14#include "llvm/ADT/StringSwitch.h"
15#include "llvm/Support/Path.h"
16#include "llvm/Support/SpecialCaseList.h"
17#include "llvm/Support/VirtualFileSystem.h"
18#include "llvm/TargetParser/AArch64TargetParser.h"
19#include "llvm/TargetParser/RISCVTargetParser.h"
20#include "llvm/TargetParser/TargetParser.h"
21#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
22#include <memory>
23
24using namespace clang;
25using namespace clang::driver;
26using namespace llvm::opt;
27
29 SanitizerKind::Undefined | SanitizerKind::Integer |
30 SanitizerKind::LocalBounds | SanitizerKind::ImplicitConversion |
31 SanitizerKind::Nullability | SanitizerKind::CFI |
32 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;
34 SanitizerKind::Vptr | SanitizerKind::CFI;
35static const SanitizerMask NotAllowedWithTrap = SanitizerKind::Vptr;
36static const SanitizerMask NotAllowedWithMinimalRuntime = SanitizerKind::Vptr;
38 SanitizerKind::Function | SanitizerKind::KCFI;
40 SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Type |
41 SanitizerKind::Thread | SanitizerKind::Memory | SanitizerKind::DataFlow |
42 SanitizerKind::NumericalStability;
44 SanitizerKind::Address | SanitizerKind::HWAddress |
45 SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |
46 SanitizerKind::Type | SanitizerKind::MemtagStack |
47 SanitizerKind::MemtagHeap | SanitizerKind::MemtagGlobals |
48 SanitizerKind::Memory | SanitizerKind::KernelMemory | SanitizerKind::Leak |
49 SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::Bounds |
50 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
51 SanitizerKind::DataFlow | SanitizerKind::Fuzzer |
52 SanitizerKind::FuzzerNoLink | SanitizerKind::FloatDivideByZero |
53 SanitizerKind::SafeStack | SanitizerKind::ShadowCallStack |
54 SanitizerKind::Thread | SanitizerKind::ObjCCast | SanitizerKind::KCFI |
55 SanitizerKind::NumericalStability;
57 SanitizerKind::Undefined | SanitizerKind::Integer |
58 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
59 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;
61 SanitizerKind::Unreachable | SanitizerKind::Return;
62static const SanitizerMask AlwaysRecoverable = SanitizerKind::KernelAddress |
63 SanitizerKind::KernelHWAddress |
64 SanitizerKind::KCFI;
65static const SanitizerMask NeedsLTO = SanitizerKind::CFI;
67 (SanitizerKind::Undefined & ~SanitizerKind::Vptr) | SanitizerKind::Integer |
68 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
69 SanitizerKind::LocalBounds | SanitizerKind::CFI |
70 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;
71static const SanitizerMask MergeDefault = SanitizerKind::Undefined;
73 SanitizerKind::CFI | SanitizerKind::LocalBounds;
75 SanitizerKind::CFIVCall | SanitizerKind::CFINVCall |
76 SanitizerKind::CFIMFCall | SanitizerKind::CFIDerivedCast |
77 SanitizerKind::CFIUnrelatedCast;
79 TrappingSupported | SanitizerKind::Scudo | SanitizerKind::ShadowCallStack |
80 SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap |
81 SanitizerKind::MemtagGlobals | SanitizerKind::KCFI;
82
84 CoverageFunc = 1 << 0,
85 CoverageBB = 1 << 1,
86 CoverageEdge = 1 << 2,
88 CoverageTraceBB = 1 << 4, // Deprecated.
92 Coverage8bitCounters = 1 << 8, // Deprecated.
95 CoverageNoPrune = 1 << 11,
97 CoveragePCTable = 1 << 13,
103};
104
109};
110
111/// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
112/// invalid components. Returns a SanitizerMask.
113static SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
114 bool DiagnoseErrors);
115
116/// Parse -f(no-)?sanitize-coverage= flag values, diagnosing any invalid
117/// components. Returns OR of members of \c CoverageFeature enumeration.
118static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A,
119 bool DiagnoseErrors);
120
121/// Parse -fsanitize-undefined-ignore-overflow-pattern= flag values, diagnosing
122/// any invalid values. Returns a mask of excluded overflow patterns.
124 const llvm::opt::Arg *A,
125 bool DiagnoseErrors);
126
127/// Parse -f(no-)?sanitize-metadata= flag values, diagnosing any invalid
128/// components. Returns OR of members of \c BinaryMetadataFeature enumeration.
129static int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A,
130 bool DiagnoseErrors);
131
132/// Produce an argument string from ArgList \p Args, which shows how it
133/// provides some sanitizer kind from \p Mask. For example, the argument list
134/// "-fsanitize=thread,vptr -fsanitize=address" with mask \c NeedsUbsanRt
135/// would produce "-fsanitize=vptr".
136static std::string lastArgumentForMask(const Driver &D,
137 const llvm::opt::ArgList &Args,
138 SanitizerMask Mask);
139
140/// Produce an argument string from argument \p A, which shows how it provides
141/// a value in \p Mask. For instance, the argument
142/// "-fsanitize=address,alignment" with mask \c NeedsUbsanRt would produce
143/// "-fsanitize=alignment".
144static std::string describeSanitizeArg(const llvm::opt::Arg *A,
145 SanitizerMask Mask);
146
147/// Produce a string containing comma-separated names of sanitizers in \p
148/// Sanitizers set.
149static std::string toString(const clang::SanitizerSet &Sanitizers);
150
151/// Return true if an execute-only target disallows data access to code
152/// sections.
153static bool isExecuteOnlyTarget(const llvm::Triple &Triple,
154 const llvm::opt::ArgList &Args) {
155 if (Triple.isPS5())
156 return true;
157 return Args.hasFlagNoClaim(options::OPT_mexecute_only,
158 options::OPT_mno_execute_only, false);
159}
160
162 std::vector<std::string> &SCLFiles,
163 unsigned MalformedSCLErrorDiagID,
164 bool DiagnoseErrors) {
165 if (SCLFiles.empty())
166 return;
167
168 std::string BLError;
169 std::unique_ptr<llvm::SpecialCaseList> SCL(
170 llvm::SpecialCaseList::create(SCLFiles, D.getVFS(), BLError));
171 if (!SCL.get() && DiagnoseErrors)
172 D.Diag(MalformedSCLErrorDiagID) << BLError;
173}
174
175static void addDefaultIgnorelists(const Driver &D, SanitizerMask Kinds,
176 std::vector<std::string> &IgnorelistFiles,
177 bool DiagnoseErrors) {
178 struct Ignorelist {
179 const char *File;
180 SanitizerMask Mask;
181 } Ignorelists[] = {{"asan_ignorelist.txt", SanitizerKind::Address},
182 {"hwasan_ignorelist.txt", SanitizerKind::HWAddress},
183 {"memtag_ignorelist.txt", SanitizerKind::MemTag},
184 {"msan_ignorelist.txt", SanitizerKind::Memory},
185 {"nsan_ignorelist.txt", SanitizerKind::NumericalStability},
186 {"tsan_ignorelist.txt", SanitizerKind::Thread},
187 {"tysan_blacklist.txt", SanitizerKind::Type},
188 {"dfsan_abilist.txt", SanitizerKind::DataFlow},
189 {"cfi_ignorelist.txt", SanitizerKind::CFI},
190 {"ubsan_ignorelist.txt",
191 SanitizerKind::Undefined | SanitizerKind::Integer |
192 SanitizerKind::Nullability |
193 SanitizerKind::FloatDivideByZero}};
194
195 for (auto BL : Ignorelists) {
196 if (!(Kinds & BL.Mask))
197 continue;
198
199 clang::SmallString<64> Path(D.ResourceDir);
200 llvm::sys::path::append(Path, "share", BL.File);
201 if (D.getVFS().exists(Path))
202 IgnorelistFiles.push_back(std::string(Path));
203 else if (BL.Mask == SanitizerKind::CFI && DiagnoseErrors)
204 // If cfi_ignorelist.txt cannot be found in the resource dir, driver
205 // should fail.
206 D.Diag(clang::diag::err_drv_missing_sanitizer_ignorelist) << Path;
207 }
209 D, IgnorelistFiles, clang::diag::err_drv_malformed_sanitizer_ignorelist,
210 DiagnoseErrors);
211}
212
213/// Parse -f(no-)?sanitize-(coverage-)?(allow|ignore)list argument's values,
214/// diagnosing any invalid file paths and validating special case list format.
216 const llvm::opt::ArgList &Args,
217 std::vector<std::string> &SCLFiles,
218 llvm::opt::OptSpecifier SCLOptionID,
219 llvm::opt::OptSpecifier NoSCLOptionID,
220 unsigned MalformedSCLErrorDiagID,
221 bool DiagnoseErrors) {
222 for (const auto *Arg : Args) {
223 // Match -fsanitize-(coverage-)?(allow|ignore)list.
224 if (Arg->getOption().matches(SCLOptionID)) {
225 Arg->claim();
226 std::string SCLPath = Arg->getValue();
227 if (D.getVFS().exists(SCLPath)) {
228 SCLFiles.push_back(SCLPath);
229 } else if (DiagnoseErrors) {
230 D.Diag(clang::diag::err_drv_no_such_file) << SCLPath;
231 }
232 // Match -fno-sanitize-ignorelist.
233 } else if (Arg->getOption().matches(NoSCLOptionID)) {
234 Arg->claim();
235 SCLFiles.clear();
236 }
237 }
238 validateSpecialCaseListFormat(D, SCLFiles, MalformedSCLErrorDiagID,
239 DiagnoseErrors);
240}
241
242/// Sets group bits for every group that has at least one representative already
243/// enabled in \p Kinds.
245#define SANITIZER(NAME, ID)
246#define SANITIZER_GROUP(NAME, ID, ALIAS) \
247 if (Kinds & SanitizerKind::ID) \
248 Kinds |= SanitizerKind::ID##Group;
249#include "clang/Basic/Sanitizers.def"
250 return Kinds;
251}
252
253// Computes the sanitizer mask as:
254// Default + Arguments (in or out)
255// with arguments parsed from left to right.
256//
257// Error messages are printed if the AlwaysIn or AlwaysOut invariants are
258// violated, but the caller must enforce these invariants themselves.
259static SanitizerMask
260parseSanitizeArgs(const Driver &D, const llvm::opt::ArgList &Args,
261 bool DiagnoseErrors, SanitizerMask Default,
262 SanitizerMask AlwaysIn, SanitizerMask AlwaysOut, int OptInID,
263 int OptOutID) {
264 assert(!(AlwaysIn & AlwaysOut) &&
265 "parseSanitizeArgs called with contradictory in/out requirements");
266
267 SanitizerMask Output = Default;
268 // Keep track of which violations we have already reported, to avoid
269 // duplicate error messages.
270 SanitizerMask DiagnosedAlwaysInViolations;
271 SanitizerMask DiagnosedAlwaysOutViolations;
272 for (const auto *Arg : Args) {
273 if (Arg->getOption().matches(OptInID)) {
274 SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors);
275 // Report error if user explicitly tries to opt-in to an always-out
276 // sanitizer.
277 if (SanitizerMask KindsToDiagnose =
278 Add & AlwaysOut & ~DiagnosedAlwaysOutViolations) {
279 if (DiagnoseErrors) {
280 SanitizerSet SetToDiagnose;
281 SetToDiagnose.Mask |= KindsToDiagnose;
282 D.Diag(diag::err_drv_unsupported_option_argument)
283 << Arg->getSpelling() << toString(SetToDiagnose);
284 DiagnosedAlwaysOutViolations |= KindsToDiagnose;
285 }
286 }
287 Output |= expandSanitizerGroups(Add);
288 Arg->claim();
289 } else if (Arg->getOption().matches(OptOutID)) {
290 SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors);
291 // Report error if user explicitly tries to opt-out of an always-in
292 // sanitizer.
293 if (SanitizerMask KindsToDiagnose =
294 Remove & AlwaysIn & ~DiagnosedAlwaysInViolations) {
295 if (DiagnoseErrors) {
296 SanitizerSet SetToDiagnose;
297 SetToDiagnose.Mask |= KindsToDiagnose;
298 D.Diag(diag::err_drv_unsupported_option_argument)
299 << Arg->getSpelling() << toString(SetToDiagnose);
300 DiagnosedAlwaysInViolations |= KindsToDiagnose;
301 }
302 }
303 Output &= ~expandSanitizerGroups(Remove);
304 Arg->claim();
305 }
306 }
307
308 return Output;
309}
310
312 const llvm::opt::ArgList &Args,
313 bool DiagnoseErrors) {
314 SanitizerMask AlwaysTrap; // Empty
316
317 // N.B. We do *not* enforce NeverTrap. This maintains the behavior of
318 // '-fsanitize=undefined -fsanitize-trap=undefined'
319 // (clang/test/Driver/fsanitize.c ), which is that vptr is not enabled at all
320 // (not even in recover mode) in order to avoid the need for a ubsan runtime.
321 return parseSanitizeArgs(D, Args, DiagnoseErrors, TrappingDefault, AlwaysTrap,
322 NeverTrap, options::OPT_fsanitize_trap_EQ,
323 options::OPT_fno_sanitize_trap_EQ);
324}
325
327 return needsFuzzer() && !needsAsanRt() && !needsTsanRt() && !needsMsanRt();
328}
329
331 // All of these include ubsan.
332 if (needsAsanRt() || needsMsanRt() || needsNsanRt() || needsHwasanRt() ||
335 return false;
336
337 return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) ||
338 CoverageFeatures;
339}
340
342 // Link UBSAN C++ runtime very selectively, as it's needed in only very
343 // specific cases, but forces the program to depend on C++ ABI. UBSAN C++
344 // runtime is not included with other sanitizers.
345 return static_cast<bool>(Sanitizers.Mask & NeedsUbsanCxxRt &
346 ~TrapSanitizers.Mask);
347}
348
350 return !(Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
351 CfiCrossDso && !ImplicitCfiRuntime;
352}
353
355 return (Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
356 CfiCrossDso && !ImplicitCfiRuntime;
357}
358
359bool SanitizerArgs::requiresPIE() const { return NeedPIE; }
360
362 return static_cast<bool>(Sanitizers.Mask & NeedsUnwindTables);
363}
364
366 return static_cast<bool>(Sanitizers.Mask & NeedsLTO);
367}
368
370 const llvm::opt::ArgList &Args,
371 bool DiagnoseErrors) {
372 SanitizerMask AllRemove; // During the loop below, the accumulated set of
373 // sanitizers disabled by the current sanitizer
374 // argument or any argument after it.
375 SanitizerMask AllAddedKinds; // Mask of all sanitizers ever enabled by
376 // -fsanitize= flags (directly or via group
377 // expansion), some of which may be disabled
378 // later. Used to carefully prune
379 // unused-argument diagnostics.
380 SanitizerMask DiagnosedKinds; // All Kinds we have diagnosed up to now.
381 // Used to deduplicate diagnostics.
382 SanitizerMask Kinds;
383 const SanitizerMask Supported = setGroupBits(TC.getSupportedSanitizers());
384
385 CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
386 options::OPT_fno_sanitize_cfi_cross_dso, false);
387
388 ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
389
390 const Driver &D = TC.getDriver();
391 SanitizerMask TrappingKinds = parseSanitizeTrapArgs(D, Args, DiagnoseErrors);
392 SanitizerMask InvalidTrappingKinds = TrappingKinds & NotAllowedWithTrap;
393
394 MinimalRuntime =
395 Args.hasFlag(options::OPT_fsanitize_minimal_runtime,
396 options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime);
397
398 // The object size sanitizer should not be enabled at -O0.
399 Arg *OptLevel = Args.getLastArg(options::OPT_O_Group);
400 bool RemoveObjectSizeAtO0 =
401 !OptLevel || OptLevel->getOption().matches(options::OPT_O0);
402
403 for (const llvm::opt::Arg *Arg : llvm::reverse(Args)) {
404 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
405 Arg->claim();
406 SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors);
407
408 if (RemoveObjectSizeAtO0) {
409 AllRemove |= SanitizerKind::ObjectSize;
410
411 // The user explicitly enabled the object size sanitizer. Warn
412 // that this does nothing at -O0.
413 if ((Add & SanitizerKind::ObjectSize) && DiagnoseErrors)
414 D.Diag(diag::warn_drv_object_size_disabled_O0)
415 << Arg->getAsString(Args);
416 }
417
418 AllAddedKinds |= expandSanitizerGroups(Add);
419
420 // Avoid diagnosing any sanitizer which is disabled later.
421 Add &= ~AllRemove;
422 // At this point we have not expanded groups, so any unsupported
423 // sanitizers in Add are those which have been explicitly enabled.
424 // Diagnose them.
425 if (SanitizerMask KindsToDiagnose =
426 Add & InvalidTrappingKinds & ~DiagnosedKinds) {
427 if (DiagnoseErrors) {
428 std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);
429 D.Diag(diag::err_drv_argument_not_allowed_with)
430 << Desc << "-fsanitize-trap=undefined";
431 }
432 DiagnosedKinds |= KindsToDiagnose;
433 }
434 Add &= ~InvalidTrappingKinds;
435
436 if (MinimalRuntime) {
437 if (SanitizerMask KindsToDiagnose =
438 Add & NotAllowedWithMinimalRuntime & ~DiagnosedKinds) {
439 if (DiagnoseErrors) {
440 std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);
441 D.Diag(diag::err_drv_argument_not_allowed_with)
442 << Desc << "-fsanitize-minimal-runtime";
443 }
444 DiagnosedKinds |= KindsToDiagnose;
445 }
446 Add &= ~NotAllowedWithMinimalRuntime;
447 }
448
449 if (llvm::opt::Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
450 StringRef CM = A->getValue();
451 if (CM != "small" &&
452 (Add & SanitizerKind::Function & ~DiagnosedKinds)) {
453 if (DiagnoseErrors)
454 D.Diag(diag::err_drv_argument_only_allowed_with)
455 << "-fsanitize=function"
456 << "-mcmodel=small";
458 DiagnosedKinds |= SanitizerKind::Function;
459 }
460 }
461 // -fsanitize=function and -fsanitize=kcfi instrument indirect function
462 // calls to load a type hash before the function label. Therefore, an
463 // execute-only target doesn't support the function and kcfi sanitizers.
464 const llvm::Triple &Triple = TC.getTriple();
465 if (isExecuteOnlyTarget(Triple, Args)) {
466 if (SanitizerMask KindsToDiagnose =
467 Add & NotAllowedWithExecuteOnly & ~DiagnosedKinds) {
468 if (DiagnoseErrors) {
469 std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);
470 llvm::opt::Arg *A = Args.getLastArgNoClaim(
471 options::OPT_mexecute_only, options::OPT_mno_execute_only);
472 if (A && A->getOption().matches(options::OPT_mexecute_only))
473 D.Diag(diag::err_drv_argument_not_allowed_with)
474 << Desc << A->getAsString(Args);
475 else
476 D.Diag(diag::err_drv_unsupported_opt_for_target)
477 << Desc << Triple.str();
478 }
479 DiagnosedKinds |= KindsToDiagnose;
480 }
481 Add &= ~NotAllowedWithExecuteOnly;
482 }
483
484 // FIXME: Make CFI on member function calls compatible with cross-DSO CFI.
485 // There are currently two problems:
486 // - Virtual function call checks need to pass a pointer to the function
487 // address to llvm.type.test and a pointer to the address point to the
488 // diagnostic function. Currently we pass the same pointer to both
489 // places.
490 // - Non-virtual function call checks may need to check multiple type
491 // identifiers.
492 // Fixing both of those may require changes to the cross-DSO CFI
493 // interface.
494 if (CfiCrossDso && (Add & SanitizerKind::CFIMFCall & ~DiagnosedKinds)) {
495 if (DiagnoseErrors)
496 D.Diag(diag::err_drv_argument_not_allowed_with)
497 << "-fsanitize=cfi-mfcall"
498 << "-fsanitize-cfi-cross-dso";
499 Add &= ~SanitizerKind::CFIMFCall;
500 DiagnosedKinds |= SanitizerKind::CFIMFCall;
501 }
502
503 if (SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
504 if (DiagnoseErrors) {
505 std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);
506 D.Diag(diag::err_drv_unsupported_opt_for_target)
507 << Desc << TC.getTriple().str();
508 }
509 DiagnosedKinds |= KindsToDiagnose;
510 }
511 Add &= Supported;
512
513 // Test for -fno-rtti + explicit -fsanitizer=vptr before expanding groups
514 // so we don't error out if -fno-rtti and -fsanitize=undefined were
515 // passed.
516 if ((Add & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {
517 if (const llvm::opt::Arg *NoRTTIArg = TC.getRTTIArg()) {
518 assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) &&
519 "RTTI disabled without -fno-rtti option?");
520 // The user explicitly passed -fno-rtti with -fsanitize=vptr, but
521 // the vptr sanitizer requires RTTI, so this is a user error.
522 if (DiagnoseErrors)
523 D.Diag(diag::err_drv_argument_not_allowed_with)
524 << "-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
525 } else {
526 // The vptr sanitizer requires RTTI, but RTTI is disabled (by
527 // default). Warn that the vptr sanitizer is being disabled.
528 if (DiagnoseErrors)
529 D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
530 }
531
532 // Take out the Vptr sanitizer from the enabled sanitizers
533 AllRemove |= SanitizerKind::Vptr;
534 }
535
536 Add = expandSanitizerGroups(Add);
537 // Group expansion may have enabled a sanitizer which is disabled later.
538 Add &= ~AllRemove;
539 // Silently discard any unsupported sanitizers implicitly enabled through
540 // group expansion.
541 Add &= ~InvalidTrappingKinds;
542 if (MinimalRuntime) {
543 Add &= ~NotAllowedWithMinimalRuntime;
544 }
545 // NotAllowedWithExecuteOnly is silently discarded on an execute-only
546 // target if implicitly enabled through group expansion.
547 if (isExecuteOnlyTarget(Triple, Args))
548 Add &= ~NotAllowedWithExecuteOnly;
549 if (CfiCrossDso)
550 Add &= ~SanitizerKind::CFIMFCall;
551 // -fsanitize=undefined does not expand to signed-integer-overflow in
552 // -fwrapv (implied by -fno-strict-overflow) mode.
553 if (Add & SanitizerKind::UndefinedGroup) {
554 bool S = Args.hasFlagNoClaim(options::OPT_fno_strict_overflow,
555 options::OPT_fstrict_overflow, false);
556 if (Args.hasFlagNoClaim(options::OPT_fwrapv, options::OPT_fno_wrapv, S))
557 Add &= ~SanitizerKind::SignedIntegerOverflow;
558 }
559 Add &= Supported;
560
561 if (Add & SanitizerKind::Fuzzer)
562 Add |= SanitizerKind::FuzzerNoLink;
563
564 // Enable coverage if the fuzzing flag is set.
565 if (Add & SanitizerKind::FuzzerNoLink) {
566 CoverageFeatures |= CoverageInline8bitCounters | CoverageIndirCall |
568 // Due to TLS differences, stack depth tracking is only enabled on Linux
569 if (TC.getTriple().isOSLinux())
570 CoverageFeatures |= CoverageStackDepth;
571 }
572
573 Kinds |= Add;
574 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
575 Arg->claim();
576 SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors);
577 AllRemove |= expandSanitizerGroups(Remove);
578 }
579 }
580
581 std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
582 std::make_pair(SanitizerKind::Address,
583 SanitizerKind::Thread | SanitizerKind::Memory),
584 std::make_pair(SanitizerKind::Type,
585 SanitizerKind::Address | SanitizerKind::KernelAddress |
586 SanitizerKind::Memory | SanitizerKind::Leak |
587 SanitizerKind::Thread | SanitizerKind::KernelAddress),
588 std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory),
589 std::make_pair(SanitizerKind::Leak,
590 SanitizerKind::Thread | SanitizerKind::Memory),
591 std::make_pair(SanitizerKind::KernelAddress,
592 SanitizerKind::Address | SanitizerKind::Leak |
593 SanitizerKind::Thread | SanitizerKind::Memory),
594 std::make_pair(SanitizerKind::HWAddress,
595 SanitizerKind::Address | SanitizerKind::Thread |
596 SanitizerKind::Memory | SanitizerKind::KernelAddress),
597 std::make_pair(SanitizerKind::Scudo,
598 SanitizerKind::Address | SanitizerKind::HWAddress |
599 SanitizerKind::Leak | SanitizerKind::Thread |
600 SanitizerKind::Memory | SanitizerKind::KernelAddress),
601 std::make_pair(SanitizerKind::SafeStack,
602 (TC.getTriple().isOSFuchsia() ? SanitizerMask()
603 : SanitizerKind::Leak) |
604 SanitizerKind::Address | SanitizerKind::HWAddress |
605 SanitizerKind::Thread | SanitizerKind::Memory |
606 SanitizerKind::KernelAddress),
607 std::make_pair(SanitizerKind::KernelHWAddress,
608 SanitizerKind::Address | SanitizerKind::HWAddress |
609 SanitizerKind::Leak | SanitizerKind::Thread |
610 SanitizerKind::Memory | SanitizerKind::KernelAddress |
611 SanitizerKind::SafeStack),
612 std::make_pair(SanitizerKind::KernelMemory,
613 SanitizerKind::Address | SanitizerKind::HWAddress |
614 SanitizerKind::Leak | SanitizerKind::Thread |
615 SanitizerKind::Memory | SanitizerKind::KernelAddress |
616 SanitizerKind::Scudo | SanitizerKind::SafeStack),
617 std::make_pair(SanitizerKind::MemTag, SanitizerKind::Address |
618 SanitizerKind::KernelAddress |
619 SanitizerKind::HWAddress |
620 SanitizerKind::KernelHWAddress),
621 std::make_pair(SanitizerKind::KCFI, SanitizerKind::Function),
622 std::make_pair(SanitizerKind::Realtime,
623 SanitizerKind::Address | SanitizerKind::Thread |
624 SanitizerKind::Undefined | SanitizerKind::Memory)};
625
626 // Enable toolchain specific default sanitizers if not explicitly disabled.
627 SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove;
628
629 // Disable default sanitizers that are incompatible with explicitly requested
630 // ones.
631 for (auto G : IncompatibleGroups) {
632 SanitizerMask Group = G.first;
633 if ((Default & Group) && (Kinds & G.second))
634 Default &= ~Group;
635 }
636
637 Kinds |= Default;
638
639 // We disable the vptr sanitizer if it was enabled by group expansion but RTTI
640 // is disabled.
641 if ((Kinds & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {
642 Kinds &= ~SanitizerKind::Vptr;
643 }
644
645 // Check that LTO is enabled if we need it.
646 if ((Kinds & NeedsLTO) && !D.isUsingLTO() && DiagnoseErrors) {
647 D.Diag(diag::err_drv_argument_only_allowed_with)
648 << lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto";
649 }
650
651 if ((Kinds & SanitizerKind::ShadowCallStack) && TC.getTriple().isAArch64() &&
652 !llvm::AArch64::isX18ReservedByDefault(TC.getTriple()) &&
653 !Args.hasArg(options::OPT_ffixed_x18) && DiagnoseErrors) {
654 D.Diag(diag::err_drv_argument_only_allowed_with)
655 << lastArgumentForMask(D, Args, Kinds & SanitizerKind::ShadowCallStack)
656 << "-ffixed-x18";
657 }
658
659 // Report error if there are non-trapping sanitizers that require
660 // c++abi-specific parts of UBSan runtime, and they are not provided by the
661 // toolchain. We don't have a good way to check the latter, so we just
662 // check if the toolchan supports vptr.
663 if (~Supported & SanitizerKind::Vptr) {
664 SanitizerMask KindsToDiagnose = Kinds & ~TrappingKinds & NeedsUbsanCxxRt;
665 // The runtime library supports the Microsoft C++ ABI, but only well enough
666 // for CFI. FIXME: Remove this once we support vptr on Windows.
667 if (TC.getTriple().isOSWindows())
668 KindsToDiagnose &= ~SanitizerKind::CFI;
669 if (KindsToDiagnose) {
670 SanitizerSet S;
671 S.Mask = KindsToDiagnose;
672 if (DiagnoseErrors)
673 D.Diag(diag::err_drv_unsupported_opt_for_target)
674 << ("-fno-sanitize-trap=" + toString(S)) << TC.getTriple().str();
675 Kinds &= ~KindsToDiagnose;
676 }
677 }
678
679 // Warn about incompatible groups of sanitizers.
680 for (auto G : IncompatibleGroups) {
681 SanitizerMask Group = G.first;
682 if (Kinds & Group) {
683 if (SanitizerMask Incompatible = Kinds & G.second) {
684 if (DiagnoseErrors)
685 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
686 << lastArgumentForMask(D, Args, Group)
687 << lastArgumentForMask(D, Args, Incompatible);
688 Kinds &= ~Incompatible;
689 }
690 }
691 }
692 // FIXME: Currently -fsanitize=leak is silently ignored in the presence of
693 // -fsanitize=address. Perhaps it should print an error, or perhaps
694 // -f(-no)sanitize=leak should change whether leak detection is enabled by
695 // default in ASan?
696
697 // Parse -f(no-)?sanitize-recover flags.
698 SanitizerMask RecoverableKinds = parseSanitizeArgs(
699 D, Args, DiagnoseErrors, RecoverableByDefault, AlwaysRecoverable,
700 Unrecoverable, options::OPT_fsanitize_recover_EQ,
701 options::OPT_fno_sanitize_recover_EQ);
702 RecoverableKinds |= AlwaysRecoverable;
703 RecoverableKinds &= ~Unrecoverable;
704 RecoverableKinds &= Kinds;
705
706 TrappingKinds &= Kinds;
707 RecoverableKinds &= ~TrappingKinds;
708
709 // Parse -f(no-)?sanitize-nonmerged-handlers flags
710 SanitizerMask MergeKinds =
711 parseSanitizeArgs(D, Args, DiagnoseErrors, MergeDefault, {}, {},
712 options::OPT_fsanitize_merge_handlers_EQ,
713 options::OPT_fno_sanitize_merge_handlers_EQ);
714 MergeKinds &= Kinds;
715
716 // Setup ignorelist files.
717 // Add default ignorelist from resource directory for activated sanitizers,
718 // and validate special case lists format.
719 if (!Args.hasArgNoClaim(options::OPT_fno_sanitize_ignorelist))
720 addDefaultIgnorelists(D, Kinds, SystemIgnorelistFiles, DiagnoseErrors);
721
722 // Parse -f(no-)?sanitize-ignorelist options.
723 // This also validates special case lists format.
725 D, Args, UserIgnorelistFiles, options::OPT_fsanitize_ignorelist_EQ,
726 options::OPT_fno_sanitize_ignorelist,
727 clang::diag::err_drv_malformed_sanitizer_ignorelist, DiagnoseErrors);
728
729 // Parse -f[no-]sanitize-memory-track-origins[=level] options.
730 if (AllAddedKinds & SanitizerKind::Memory) {
731 if (Arg *A =
732 Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
733 options::OPT_fno_sanitize_memory_track_origins)) {
734 if (!A->getOption().matches(
735 options::OPT_fno_sanitize_memory_track_origins)) {
736 StringRef S = A->getValue();
737 if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
738 MsanTrackOrigins > 2) {
739 if (DiagnoseErrors)
740 D.Diag(clang::diag::err_drv_invalid_value)
741 << A->getAsString(Args) << S;
742 }
743 }
744 }
745 MsanUseAfterDtor = Args.hasFlag(
746 options::OPT_fsanitize_memory_use_after_dtor,
747 options::OPT_fno_sanitize_memory_use_after_dtor, MsanUseAfterDtor);
748 MsanParamRetval = Args.hasFlag(
749 options::OPT_fsanitize_memory_param_retval,
750 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
751 } else if (AllAddedKinds & SanitizerKind::KernelMemory) {
752 MsanUseAfterDtor = false;
753 MsanParamRetval = Args.hasFlag(
754 options::OPT_fsanitize_memory_param_retval,
755 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
756 } else {
757 MsanUseAfterDtor = false;
758 MsanParamRetval = false;
759 }
760
761 if (AllAddedKinds & SanitizerKind::MemTag) {
762 StringRef S =
763 Args.getLastArgValue(options::OPT_fsanitize_memtag_mode_EQ, "sync");
764 if (S == "async" || S == "sync") {
765 MemtagMode = S.str();
766 } else {
767 D.Diag(clang::diag::err_drv_invalid_value_with_suggestion)
768 << "-fsanitize-memtag-mode=" << S << "{async, sync}";
769 MemtagMode = "sync";
770 }
771 }
772
773 if (AllAddedKinds & SanitizerKind::Thread) {
774 TsanMemoryAccess = Args.hasFlag(
775 options::OPT_fsanitize_thread_memory_access,
776 options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess);
777 TsanFuncEntryExit = Args.hasFlag(
778 options::OPT_fsanitize_thread_func_entry_exit,
779 options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit);
780 TsanAtomics =
781 Args.hasFlag(options::OPT_fsanitize_thread_atomics,
782 options::OPT_fno_sanitize_thread_atomics, TsanAtomics);
783 }
784
785 if (AllAddedKinds & SanitizerKind::CFI) {
786 // Without PIE, external function address may resolve to a PLT record, which
787 // can not be verified by the target module.
788 NeedPIE |= CfiCrossDso;
789 CfiICallGeneralizePointers =
790 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
791
792 CfiICallNormalizeIntegers =
793 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
794
795 if (CfiCrossDso && CfiICallGeneralizePointers && DiagnoseErrors)
796 D.Diag(diag::err_drv_argument_not_allowed_with)
797 << "-fsanitize-cfi-cross-dso"
798 << "-fsanitize-cfi-icall-generalize-pointers";
799
800 CfiCanonicalJumpTables =
801 Args.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables,
802 options::OPT_fno_sanitize_cfi_canonical_jump_tables, true);
803 }
804
805 if (AllAddedKinds & SanitizerKind::KCFI) {
806 CfiICallNormalizeIntegers =
807 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
808
809 if (AllAddedKinds & SanitizerKind::CFI && DiagnoseErrors)
810 D.Diag(diag::err_drv_argument_not_allowed_with)
811 << "-fsanitize=kcfi"
812 << lastArgumentForMask(D, Args, SanitizerKind::CFI);
813 }
814
815 Stats = Args.hasFlag(options::OPT_fsanitize_stats,
816 options::OPT_fno_sanitize_stats, false);
817
818 if (MinimalRuntime) {
819 SanitizerMask IncompatibleMask =
820 Kinds & ~setGroupBits(CompatibleWithMinimalRuntime);
821 if (IncompatibleMask && DiagnoseErrors)
822 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
823 << "-fsanitize-minimal-runtime"
824 << lastArgumentForMask(D, Args, IncompatibleMask);
825
826 SanitizerMask NonTrappingCfi = Kinds & SanitizerKind::CFI & ~TrappingKinds;
827 if (NonTrappingCfi && DiagnoseErrors)
828 D.Diag(clang::diag::err_drv_argument_only_allowed_with)
829 << "fsanitize-minimal-runtime"
830 << "fsanitize-trap=cfi";
831 }
832
833 for (const auto *Arg : Args.filtered(
834 options::OPT_fsanitize_undefined_ignore_overflow_pattern_EQ)) {
835 Arg->claim();
836 OverflowPatternExclusions |=
837 parseOverflowPatternExclusionValues(D, Arg, DiagnoseErrors);
838 }
839
840 // Parse -f(no-)?sanitize-coverage flags if coverage is supported by the
841 // enabled sanitizers.
842 for (const auto *Arg : Args) {
843 if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
844 int LegacySanitizeCoverage;
845 if (Arg->getNumValues() == 1 &&
846 !StringRef(Arg->getValue(0))
847 .getAsInteger(0, LegacySanitizeCoverage)) {
848 CoverageFeatures = 0;
849 Arg->claim();
850 if (LegacySanitizeCoverage != 0 && DiagnoseErrors) {
851 D.Diag(diag::warn_drv_deprecated_arg)
852 << Arg->getAsString(Args) << /*hasReplacement=*/true
853 << "-fsanitize-coverage=trace-pc-guard";
854 }
855 continue;
856 }
857 CoverageFeatures |= parseCoverageFeatures(D, Arg, DiagnoseErrors);
858
859 // Disable coverage and not claim the flags if there is at least one
860 // non-supporting sanitizer.
861 if (!(AllAddedKinds & ~AllRemove & ~setGroupBits(SupportsCoverage))) {
862 Arg->claim();
863 } else {
864 CoverageFeatures = 0;
865 }
866 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
867 Arg->claim();
868 CoverageFeatures &= ~parseCoverageFeatures(D, Arg, DiagnoseErrors);
869 }
870 }
871 // Choose at most one coverage type: function, bb, or edge.
872 if (DiagnoseErrors) {
873 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageBB))
874 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
875 << "-fsanitize-coverage=func"
876 << "-fsanitize-coverage=bb";
877 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageEdge))
878 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
879 << "-fsanitize-coverage=func"
880 << "-fsanitize-coverage=edge";
881 if ((CoverageFeatures & CoverageBB) && (CoverageFeatures & CoverageEdge))
882 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
883 << "-fsanitize-coverage=bb"
884 << "-fsanitize-coverage=edge";
885 // Basic block tracing and 8-bit counters require some type of coverage
886 // enabled.
887 if (CoverageFeatures & CoverageTraceBB)
888 D.Diag(clang::diag::warn_drv_deprecated_arg)
889 << "-fsanitize-coverage=trace-bb" << /*hasReplacement=*/true
890 << "-fsanitize-coverage=trace-pc-guard";
891 if (CoverageFeatures & Coverage8bitCounters)
892 D.Diag(clang::diag::warn_drv_deprecated_arg)
893 << "-fsanitize-coverage=8bit-counters" << /*hasReplacement=*/true
894 << "-fsanitize-coverage=trace-pc-guard";
895 }
896
897 int InsertionPointTypes = CoverageFunc | CoverageBB | CoverageEdge;
898 int InstrumentationTypes = CoverageTracePC | CoverageTracePCGuard |
902 if ((CoverageFeatures & InsertionPointTypes) &&
903 !(CoverageFeatures & InstrumentationTypes) && DiagnoseErrors) {
904 D.Diag(clang::diag::warn_drv_deprecated_arg)
905 << "-fsanitize-coverage=[func|bb|edge]" << /*hasReplacement=*/true
906 << "-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc],["
907 "control-flow]";
908 }
909
910 // trace-pc w/o func/bb/edge implies edge.
911 if (!(CoverageFeatures & InsertionPointTypes)) {
912 if (CoverageFeatures &
915 CoverageFeatures |= CoverageEdge;
916
917 if (CoverageFeatures & CoverageStackDepth)
918 CoverageFeatures |= CoverageFunc;
919 }
920
921 // Parse -fsanitize-coverage-(allow|ignore)list options if coverage enabled.
922 // This also validates special case lists format.
923 // Here, OptSpecifier() acts as a never-matching command-line argument.
924 // So, there is no way to clear coverage lists but you can append to them.
925 if (CoverageFeatures) {
927 D, Args, CoverageAllowlistFiles,
928 options::OPT_fsanitize_coverage_allowlist, OptSpecifier(),
929 clang::diag::err_drv_malformed_sanitizer_coverage_allowlist,
930 DiagnoseErrors);
932 D, Args, CoverageIgnorelistFiles,
933 options::OPT_fsanitize_coverage_ignorelist, OptSpecifier(),
934 clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist,
935 DiagnoseErrors);
936 }
937
938 // Parse -f(no-)?sanitize-metadata.
939 for (const auto *Arg :
940 Args.filtered(options::OPT_fexperimental_sanitize_metadata_EQ,
941 options::OPT_fno_experimental_sanitize_metadata_EQ)) {
942 if (Arg->getOption().matches(
943 options::OPT_fexperimental_sanitize_metadata_EQ)) {
944 Arg->claim();
945 BinaryMetadataFeatures |=
946 parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);
947 } else {
948 Arg->claim();
949 BinaryMetadataFeatures &=
950 ~parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);
951 }
952 }
953
954 // Parse -fsanitize-metadata-ignorelist option if enabled.
955 if (BinaryMetadataFeatures) {
957 D, Args, BinaryMetadataIgnorelistFiles,
958 options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ,
959 OptSpecifier(), // Cannot clear ignore list, only append.
960 clang::diag::err_drv_malformed_sanitizer_metadata_ignorelist,
961 DiagnoseErrors);
962 }
963
964 SharedRuntime = Args.hasFlag(
965 options::OPT_shared_libsan, options::OPT_static_libsan,
966 TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() ||
967 TC.getTriple().isOSDarwin() || TC.getTriple().isOSWindows());
968 if (!SharedRuntime && TC.getTriple().isOSWindows()) {
969 Arg *A =
970 Args.getLastArg(options::OPT_shared_libsan, options::OPT_static_libsan);
971 D.Diag(clang::diag::err_drv_unsupported_opt_for_target)
972 << A->getSpelling() << TC.getTriple().str();
973 }
974
975 ImplicitCfiRuntime = TC.getTriple().isAndroid();
976
977 if (AllAddedKinds & SanitizerKind::Address) {
978 NeedPIE |= TC.getTriple().isOSFuchsia();
979 if (Arg *A =
980 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
981 StringRef S = A->getValue();
982 // Legal values are 0 and 1, 2, but in future we may add more levels.
983 if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
984 AsanFieldPadding > 2) &&
985 DiagnoseErrors) {
986 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
987 }
988 }
989
990 if (Arg *WindowsDebugRTArg =
991 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
992 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
993 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
994 switch (WindowsDebugRTArg->getOption().getID()) {
995 case options::OPT__SLASH_MTd:
996 case options::OPT__SLASH_MDd:
997 case options::OPT__SLASH_LDd:
998 if (DiagnoseErrors) {
999 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
1000 << WindowsDebugRTArg->getAsString(Args)
1001 << lastArgumentForMask(D, Args, SanitizerKind::Address);
1002 D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
1003 }
1004 }
1005 }
1006
1007 StableABI = Args.hasFlag(options::OPT_fsanitize_stable_abi,
1008 options::OPT_fno_sanitize_stable_abi, false);
1009
1010 AsanUseAfterScope = Args.hasFlag(
1011 options::OPT_fsanitize_address_use_after_scope,
1012 options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);
1013
1014 AsanPoisonCustomArrayCookie = Args.hasFlag(
1015 options::OPT_fsanitize_address_poison_custom_array_cookie,
1016 options::OPT_fno_sanitize_address_poison_custom_array_cookie,
1017 AsanPoisonCustomArrayCookie);
1018
1019 AsanOutlineInstrumentation =
1020 Args.hasFlag(options::OPT_fsanitize_address_outline_instrumentation,
1021 options::OPT_fno_sanitize_address_outline_instrumentation,
1022 AsanOutlineInstrumentation);
1023
1024 AsanGlobalsDeadStripping = Args.hasFlag(
1025 options::OPT_fsanitize_address_globals_dead_stripping,
1026 options::OPT_fno_sanitize_address_globals_dead_stripping, true);
1027
1028 // Enable ODR indicators which allow better handling of mixed instrumented
1029 // and uninstrumented globals. Disable them for Windows where weak odr
1030 // indicators (.weak.__odr_asan_gen*) may cause multiple definition linker
1031 // errors in the absence of -lldmingw.
1032 AsanUseOdrIndicator =
1033 Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
1034 options::OPT_fno_sanitize_address_use_odr_indicator,
1035 !TC.getTriple().isOSWindows());
1036
1037 if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) {
1038 AsanInvalidPointerCmp = true;
1039 }
1040
1041 if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) {
1042 AsanInvalidPointerSub = true;
1043 }
1044
1045 if (TC.getTriple().isOSDarwin() &&
1046 (Args.hasArg(options::OPT_mkernel) ||
1047 Args.hasArg(options::OPT_fapple_kext))) {
1048 AsanDtorKind = llvm::AsanDtorKind::None;
1049 }
1050
1051 if (const auto *Arg =
1052 Args.getLastArg(options::OPT_sanitize_address_destructor_EQ)) {
1053 auto parsedAsanDtorKind = AsanDtorKindFromString(Arg->getValue());
1054 if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid && DiagnoseErrors) {
1055 TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)
1056 << Arg->getSpelling() << Arg->getValue();
1057 }
1058 AsanDtorKind = parsedAsanDtorKind;
1059 }
1060
1061 if (const auto *Arg = Args.getLastArg(
1062 options::OPT_sanitize_address_use_after_return_EQ)) {
1063 auto parsedAsanUseAfterReturn =
1065 if (parsedAsanUseAfterReturn ==
1066 llvm::AsanDetectStackUseAfterReturnMode::Invalid &&
1067 DiagnoseErrors) {
1068 TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)
1069 << Arg->getSpelling() << Arg->getValue();
1070 }
1071 AsanUseAfterReturn = parsedAsanUseAfterReturn;
1072 }
1073
1074 } else {
1075 AsanUseAfterScope = false;
1076 // -fsanitize=pointer-compare/pointer-subtract requires -fsanitize=address.
1077 SanitizerMask DetectInvalidPointerPairs =
1078 SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract;
1079 if ((AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) &&
1080 DiagnoseErrors) {
1081 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)
1082 << lastArgumentForMask(D, Args,
1083 SanitizerKind::PointerCompare |
1084 SanitizerKind::PointerSubtract)
1085 << "-fsanitize=address";
1086 }
1087 }
1088
1089 if (AllAddedKinds & SanitizerKind::HWAddress) {
1090 if (Arg *HwasanAbiArg =
1091 Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {
1092 HwasanAbi = HwasanAbiArg->getValue();
1093 if (HwasanAbi != "platform" && HwasanAbi != "interceptor" &&
1094 DiagnoseErrors)
1095 D.Diag(clang::diag::err_drv_invalid_value)
1096 << HwasanAbiArg->getAsString(Args) << HwasanAbi;
1097 } else {
1098 HwasanAbi = "interceptor";
1099 }
1100 if (TC.getTriple().getArch() == llvm::Triple::x86_64)
1101 HwasanUseAliases = Args.hasFlag(
1102 options::OPT_fsanitize_hwaddress_experimental_aliasing,
1103 options::OPT_fno_sanitize_hwaddress_experimental_aliasing,
1104 HwasanUseAliases);
1105 }
1106
1107 if (AllAddedKinds & SanitizerKind::SafeStack) {
1108 // SafeStack runtime is built into the system on Android and Fuchsia.
1109 SafeStackRuntime =
1110 !TC.getTriple().isAndroid() && !TC.getTriple().isOSFuchsia();
1111 }
1112
1113 LinkRuntimes =
1114 Args.hasFlag(options::OPT_fsanitize_link_runtime,
1115 options::OPT_fno_sanitize_link_runtime, LinkRuntimes);
1116
1117 // Parse -link-cxx-sanitizer flag.
1118 LinkCXXRuntimes = D.CCCIsCXX();
1119 LinkCXXRuntimes =
1120 Args.hasFlag(options::OPT_fsanitize_link_cxx_runtime,
1121 options::OPT_fno_sanitize_link_cxx_runtime, LinkCXXRuntimes);
1122
1123 NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile,
1124 options::OPT_fmemory_profile_EQ,
1125 options::OPT_fno_memory_profile, false);
1126
1127 // Finally, initialize the set of available and recoverable sanitizers.
1128 Sanitizers.Mask |= Kinds;
1129 RecoverableSanitizers.Mask |= RecoverableKinds;
1130 TrapSanitizers.Mask |= TrappingKinds;
1131 assert(!(RecoverableKinds & TrappingKinds) &&
1132 "Overlap between recoverable and trapping sanitizers");
1133
1134 MergeHandlers.Mask |= MergeKinds;
1135}
1136
1137static std::string toString(const clang::SanitizerSet &Sanitizers) {
1138 std::string Res;
1139#define SANITIZER(NAME, ID) \
1140 if (Sanitizers.has(SanitizerKind::ID)) { \
1141 if (!Res.empty()) \
1142 Res += ","; \
1143 Res += NAME; \
1144 }
1145#include "clang/Basic/Sanitizers.def"
1146 return Res;
1147}
1148
1149static void addSpecialCaseListOpt(const llvm::opt::ArgList &Args,
1150 llvm::opt::ArgStringList &CmdArgs,
1151 const char *SCLOptFlag,
1152 const std::vector<std::string> &SCLFiles) {
1153 for (const auto &SCLPath : SCLFiles) {
1154 SmallString<64> SCLOpt(SCLOptFlag);
1155 SCLOpt += SCLPath;
1156 CmdArgs.push_back(Args.MakeArgString(SCLOpt));
1157 }
1158}
1159
1160static void addIncludeLinkerOption(const ToolChain &TC,
1161 const llvm::opt::ArgList &Args,
1162 llvm::opt::ArgStringList &CmdArgs,
1163 StringRef SymbolName) {
1164 SmallString<64> LinkerOptionFlag;
1165 LinkerOptionFlag = "--linker-option=/include:";
1166 if (TC.getTriple().getArch() == llvm::Triple::x86) {
1167 // Win32 mangles C function names with a '_' prefix.
1168 LinkerOptionFlag += '_';
1169 }
1170 LinkerOptionFlag += SymbolName;
1171 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
1172}
1173
1174static bool hasTargetFeatureMTE(const llvm::opt::ArgStringList &CmdArgs) {
1175 for (auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End;
1176 ++Start) {
1177 auto It = std::find(Start, End, StringRef("+mte"));
1178 if (It == End)
1179 break;
1180 if (It > Start && *std::prev(It) == StringRef("-target-feature"))
1181 return true;
1182 Start = It;
1183 }
1184 return false;
1185}
1186
1187void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
1188 llvm::opt::ArgStringList &CmdArgs,
1189 types::ID InputType) const {
1190 // NVPTX doesn't currently support sanitizers. Bailing out here means
1191 // that e.g. -fsanitize=address applies only to host code, which is what we
1192 // want for now.
1193 if (TC.getTriple().isNVPTX())
1194 return;
1195 // AMDGPU sanitizer support is experimental and controlled by -fgpu-sanitize.
1196 bool GPUSanitize = false;
1197 if (TC.getTriple().isAMDGPU()) {
1198 if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
1199 true))
1200 return;
1201 GPUSanitize = true;
1202 }
1203
1204 // Translate available CoverageFeatures to corresponding clang-cc1 flags.
1205 // Do it even if Sanitizers.empty() since some forms of coverage don't require
1206 // sanitizers.
1207 std::pair<int, const char *> CoverageFlags[] = {
1208 std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"),
1209 std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"),
1210 std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"),
1211 std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"),
1212 std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"),
1213 std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"),
1214 std::make_pair(CoverageTraceDiv, "-fsanitize-coverage-trace-div"),
1215 std::make_pair(CoverageTraceGep, "-fsanitize-coverage-trace-gep"),
1216 std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"),
1217 std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"),
1218 std::make_pair(CoverageTracePCGuard,
1219 "-fsanitize-coverage-trace-pc-guard"),
1220 std::make_pair(CoverageInline8bitCounters,
1221 "-fsanitize-coverage-inline-8bit-counters"),
1222 std::make_pair(CoverageInlineBoolFlag,
1223 "-fsanitize-coverage-inline-bool-flag"),
1224 std::make_pair(CoveragePCTable, "-fsanitize-coverage-pc-table"),
1225 std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune"),
1226 std::make_pair(CoverageStackDepth, "-fsanitize-coverage-stack-depth"),
1227 std::make_pair(CoverageTraceLoads, "-fsanitize-coverage-trace-loads"),
1228 std::make_pair(CoverageTraceStores, "-fsanitize-coverage-trace-stores"),
1229 std::make_pair(CoverageControlFlow, "-fsanitize-coverage-control-flow")};
1230 for (auto F : CoverageFlags) {
1231 if (CoverageFeatures & F.first)
1232 CmdArgs.push_back(F.second);
1233 }
1235 Args, CmdArgs, "-fsanitize-coverage-allowlist=", CoverageAllowlistFiles);
1236 addSpecialCaseListOpt(Args, CmdArgs, "-fsanitize-coverage-ignorelist=",
1237 CoverageIgnorelistFiles);
1238
1239 if (!GPUSanitize) {
1240 // Translate available BinaryMetadataFeatures to corresponding clang-cc1
1241 // flags. Does not depend on any other sanitizers. Unsupported on GPUs.
1242 const std::pair<int, std::string> BinaryMetadataFlags[] = {
1243 std::make_pair(BinaryMetadataCovered, "covered"),
1244 std::make_pair(BinaryMetadataAtomics, "atomics"),
1245 std::make_pair(BinaryMetadataUAR, "uar")};
1246 for (const auto &F : BinaryMetadataFlags) {
1247 if (BinaryMetadataFeatures & F.first)
1248 CmdArgs.push_back(
1249 Args.MakeArgString("-fexperimental-sanitize-metadata=" + F.second));
1250 }
1251 addSpecialCaseListOpt(Args, CmdArgs,
1252 "-fexperimental-sanitize-metadata-ignorelist=",
1253 BinaryMetadataIgnorelistFiles);
1254 }
1255
1256 if (TC.getTriple().isOSWindows() && needsUbsanRt() &&
1257 Args.hasFlag(options::OPT_frtlib_defaultlib,
1258 options::OPT_fno_rtlib_defaultlib, true)) {
1259 // Instruct the code generator to embed linker directives in the object file
1260 // that cause the required runtime libraries to be linked.
1261 CmdArgs.push_back(
1262 Args.MakeArgString("--dependent-lib=" +
1263 TC.getCompilerRTBasename(Args, "ubsan_standalone")));
1264 if (types::isCXX(InputType))
1265 CmdArgs.push_back(Args.MakeArgString(
1266 "--dependent-lib=" +
1267 TC.getCompilerRTBasename(Args, "ubsan_standalone_cxx")));
1268 }
1269 if (TC.getTriple().isOSWindows() && needsStatsRt() &&
1270 Args.hasFlag(options::OPT_frtlib_defaultlib,
1271 options::OPT_fno_rtlib_defaultlib, true)) {
1272 CmdArgs.push_back(Args.MakeArgString(
1273 "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats_client")));
1274
1275 // The main executable must export the stats runtime.
1276 // FIXME: Only exporting from the main executable (e.g. based on whether the
1277 // translation unit defines main()) would save a little space, but having
1278 // multiple copies of the runtime shouldn't hurt.
1279 CmdArgs.push_back(Args.MakeArgString(
1280 "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats")));
1281 addIncludeLinkerOption(TC, Args, CmdArgs, "__sanitizer_stats_register");
1282 }
1283
1284 if (Sanitizers.empty())
1285 return;
1286 CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers)));
1287
1288 if (!RecoverableSanitizers.empty())
1289 CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" +
1290 toString(RecoverableSanitizers)));
1291
1292 if (!TrapSanitizers.empty())
1293 CmdArgs.push_back(
1294 Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));
1295
1296 if (!MergeHandlers.empty())
1297 CmdArgs.push_back(
1298 Args.MakeArgString("-fsanitize-merge=" + toString(MergeHandlers)));
1299
1300 addSpecialCaseListOpt(Args, CmdArgs,
1301 "-fsanitize-ignorelist=", UserIgnorelistFiles);
1302 addSpecialCaseListOpt(Args, CmdArgs,
1303 "-fsanitize-system-ignorelist=", SystemIgnorelistFiles);
1304
1305 if (OverflowPatternExclusions)
1306 Args.AddAllArgs(
1307 CmdArgs, options::OPT_fsanitize_undefined_ignore_overflow_pattern_EQ);
1308
1309 if (MsanTrackOrigins)
1310 CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" +
1311 Twine(MsanTrackOrigins)));
1312
1313 if (MsanUseAfterDtor)
1314 CmdArgs.push_back("-fsanitize-memory-use-after-dtor");
1315
1316 if (!MsanParamRetval)
1317 CmdArgs.push_back("-fno-sanitize-memory-param-retval");
1318
1319 // FIXME: Pass these parameters as function attributes, not as -llvm flags.
1320 if (!TsanMemoryAccess) {
1321 CmdArgs.push_back("-mllvm");
1322 CmdArgs.push_back("-tsan-instrument-memory-accesses=0");
1323 CmdArgs.push_back("-mllvm");
1324 CmdArgs.push_back("-tsan-instrument-memintrinsics=0");
1325 }
1326 if (!TsanFuncEntryExit) {
1327 CmdArgs.push_back("-mllvm");
1328 CmdArgs.push_back("-tsan-instrument-func-entry-exit=0");
1329 }
1330 if (!TsanAtomics) {
1331 CmdArgs.push_back("-mllvm");
1332 CmdArgs.push_back("-tsan-instrument-atomics=0");
1333 }
1334
1335 if (HwasanUseAliases) {
1336 CmdArgs.push_back("-mllvm");
1337 CmdArgs.push_back("-hwasan-experimental-use-page-aliases=1");
1338 }
1339
1340 if (CfiCrossDso)
1341 CmdArgs.push_back("-fsanitize-cfi-cross-dso");
1342
1343 if (CfiICallGeneralizePointers)
1344 CmdArgs.push_back("-fsanitize-cfi-icall-generalize-pointers");
1345
1346 if (CfiICallNormalizeIntegers)
1347 CmdArgs.push_back("-fsanitize-cfi-icall-experimental-normalize-integers");
1348
1349 if (CfiCanonicalJumpTables)
1350 CmdArgs.push_back("-fsanitize-cfi-canonical-jump-tables");
1351
1352 if (Stats)
1353 CmdArgs.push_back("-fsanitize-stats");
1354
1355 if (MinimalRuntime)
1356 CmdArgs.push_back("-fsanitize-minimal-runtime");
1357
1358 if (AsanFieldPadding)
1359 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" +
1360 Twine(AsanFieldPadding)));
1361
1362 if (AsanUseAfterScope)
1363 CmdArgs.push_back("-fsanitize-address-use-after-scope");
1364
1365 if (AsanPoisonCustomArrayCookie)
1366 CmdArgs.push_back("-fsanitize-address-poison-custom-array-cookie");
1367
1368 if (AsanGlobalsDeadStripping)
1369 CmdArgs.push_back("-fsanitize-address-globals-dead-stripping");
1370
1371 if (!AsanUseOdrIndicator)
1372 CmdArgs.push_back("-fno-sanitize-address-use-odr-indicator");
1373
1374 if (AsanInvalidPointerCmp) {
1375 CmdArgs.push_back("-mllvm");
1376 CmdArgs.push_back("-asan-detect-invalid-pointer-cmp");
1377 }
1378
1379 if (AsanInvalidPointerSub) {
1380 CmdArgs.push_back("-mllvm");
1381 CmdArgs.push_back("-asan-detect-invalid-pointer-sub");
1382 }
1383
1384 if (AsanOutlineInstrumentation) {
1385 CmdArgs.push_back("-mllvm");
1386 CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");
1387 }
1388
1389 // When emitting Stable ABI instrumentation, force outlining calls and avoid
1390 // inlining shadow memory poisoning. While this is a big performance burden
1391 // for now it allows full abstraction from implementation details.
1392 if (StableABI) {
1393 CmdArgs.push_back("-mllvm");
1394 CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");
1395 CmdArgs.push_back("-mllvm");
1396 CmdArgs.push_back("-asan-max-inline-poisoning-size=0");
1397 CmdArgs.push_back("-mllvm");
1398 CmdArgs.push_back("-asan-guard-against-version-mismatch=0");
1399 }
1400
1401 // Only pass the option to the frontend if the user requested,
1402 // otherwise the frontend will just use the codegen default.
1403 if (AsanDtorKind != llvm::AsanDtorKind::Invalid) {
1404 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-destructor=" +
1405 AsanDtorKindToString(AsanDtorKind)));
1406 }
1407
1408 if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
1409 CmdArgs.push_back(Args.MakeArgString(
1410 "-fsanitize-address-use-after-return=" +
1411 AsanDetectStackUseAfterReturnModeToString(AsanUseAfterReturn)));
1412 }
1413
1414 if (!HwasanAbi.empty()) {
1415 CmdArgs.push_back("-default-function-attr");
1416 CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi));
1417 }
1418
1419 if (Sanitizers.has(SanitizerKind::HWAddress) && !HwasanUseAliases) {
1420 CmdArgs.push_back("-target-feature");
1421 CmdArgs.push_back("+tagged-globals");
1422 }
1423
1424 // MSan: Workaround for PR16386.
1425 // ASan: This is mainly to help LSan with cases such as
1426 // https://github.com/google/sanitizers/issues/373
1427 // We can't make this conditional on -fsanitize=leak, as that flag shouldn't
1428 // affect compilation.
1429 if (Sanitizers.has(SanitizerKind::Memory) ||
1430 Sanitizers.has(SanitizerKind::Address))
1431 CmdArgs.push_back("-fno-assume-sane-operator-new");
1432
1433 // libFuzzer wants to intercept calls to certain library functions, so the
1434 // following -fno-builtin-* flags force the compiler to emit interposable
1435 // libcalls to these functions. Other sanitizers effectively do the same thing
1436 // by marking all library call sites with NoBuiltin attribute in their LLVM
1437 // pass. (see llvm::maybeMarkSanitizerLibraryCallNoBuiltin)
1438 if (Sanitizers.has(SanitizerKind::FuzzerNoLink)) {
1439 CmdArgs.push_back("-fno-builtin-bcmp");
1440 CmdArgs.push_back("-fno-builtin-memcmp");
1441 CmdArgs.push_back("-fno-builtin-strncmp");
1442 CmdArgs.push_back("-fno-builtin-strcmp");
1443 CmdArgs.push_back("-fno-builtin-strncasecmp");
1444 CmdArgs.push_back("-fno-builtin-strcasecmp");
1445 CmdArgs.push_back("-fno-builtin-strstr");
1446 CmdArgs.push_back("-fno-builtin-strcasestr");
1447 CmdArgs.push_back("-fno-builtin-memmem");
1448 }
1449
1450 // Require -fvisibility= flag on non-Windows when compiling if vptr CFI is
1451 // enabled.
1452 if (Sanitizers.hasOneOf(CFIClasses) && !TC.getTriple().isOSWindows() &&
1453 !Args.hasArg(options::OPT_fvisibility_EQ)) {
1454 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)
1455 << lastArgumentForMask(TC.getDriver(), Args,
1456 Sanitizers.Mask & CFIClasses)
1457 << "-fvisibility=";
1458 }
1459
1460 if (Sanitizers.has(SanitizerKind::MemtagStack) &&
1461 !hasTargetFeatureMTE(CmdArgs))
1462 TC.getDriver().Diag(diag::err_stack_tagging_requires_hardware_feature);
1463}
1464
1465SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
1466 bool DiagnoseErrors) {
1467 assert(
1468 (A->getOption().matches(options::OPT_fsanitize_EQ) ||
1469 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
1470 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
1471 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
1472 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
1473 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ) ||
1474 A->getOption().matches(options::OPT_fsanitize_merge_handlers_EQ) ||
1475 A->getOption().matches(options::OPT_fno_sanitize_merge_handlers_EQ)) &&
1476 "Invalid argument in parseArgValues!");
1477 SanitizerMask Kinds;
1478 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1479 const char *Value = A->getValue(i);
1480 SanitizerMask Kind;
1481 // Special case: don't accept -fsanitize=all.
1482 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
1483 0 == strcmp("all", Value))
1484 Kind = SanitizerMask();
1485 else
1486 Kind = parseSanitizerValue(Value, /*AllowGroups=*/true);
1487
1488 if (Kind)
1489 Kinds |= Kind;
1490 else if (DiagnoseErrors)
1491 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1492 << A->getSpelling() << Value;
1493 }
1494 return Kinds;
1495}
1496
1498 const llvm::opt::Arg *A,
1499 bool DiagnoseErrors) {
1500 int Exclusions = 0;
1501 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1502 const char *Value = A->getValue(i);
1503 int E =
1504 llvm::StringSwitch<int>(Value)
1505 .Case("none", LangOptionsBase::None)
1506 .Case("all", LangOptionsBase::All)
1507 .Case("add-unsigned-overflow-test",
1509 .Case("add-signed-overflow-test",
1511 .Case("negated-unsigned-const", LangOptionsBase::NegUnsignedConst)
1512 .Case("unsigned-post-decr-while", LangOptionsBase::PostDecrInWhile)
1513 .Default(0);
1514 if (E == 0)
1515 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1516 << A->getSpelling() << Value;
1517 Exclusions |= E;
1518 }
1519 return Exclusions;
1520}
1521
1522int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A,
1523 bool DiagnoseErrors) {
1524 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
1525 A->getOption().matches(options::OPT_fno_sanitize_coverage));
1526 int Features = 0;
1527 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1528 const char *Value = A->getValue(i);
1529 int F = llvm::StringSwitch<int>(Value)
1530 .Case("func", CoverageFunc)
1531 .Case("bb", CoverageBB)
1532 .Case("edge", CoverageEdge)
1533 .Case("indirect-calls", CoverageIndirCall)
1534 .Case("trace-bb", CoverageTraceBB)
1535 .Case("trace-cmp", CoverageTraceCmp)
1536 .Case("trace-div", CoverageTraceDiv)
1537 .Case("trace-gep", CoverageTraceGep)
1538 .Case("8bit-counters", Coverage8bitCounters)
1539 .Case("trace-pc", CoverageTracePC)
1540 .Case("trace-pc-guard", CoverageTracePCGuard)
1541 .Case("no-prune", CoverageNoPrune)
1542 .Case("inline-8bit-counters", CoverageInline8bitCounters)
1543 .Case("inline-bool-flag", CoverageInlineBoolFlag)
1544 .Case("pc-table", CoveragePCTable)
1545 .Case("stack-depth", CoverageStackDepth)
1546 .Case("trace-loads", CoverageTraceLoads)
1547 .Case("trace-stores", CoverageTraceStores)
1548 .Case("control-flow", CoverageControlFlow)
1549 .Default(0);
1550 if (F == 0 && DiagnoseErrors)
1551 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1552 << A->getSpelling() << Value;
1553 Features |= F;
1554 }
1555 return Features;
1556}
1557
1558int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A,
1559 bool DiagnoseErrors) {
1560 assert(
1561 A->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ) ||
1562 A->getOption().matches(
1563 options::OPT_fno_experimental_sanitize_metadata_EQ));
1564 int Features = 0;
1565 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1566 const char *Value = A->getValue(i);
1567 int F = llvm::StringSwitch<int>(Value)
1568 .Case("covered", BinaryMetadataCovered)
1569 .Case("atomics", BinaryMetadataAtomics)
1570 .Case("uar", BinaryMetadataUAR)
1571 .Case("all", ~0)
1572 .Default(0);
1573 if (F == 0 && DiagnoseErrors)
1574 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1575 << A->getSpelling() << Value;
1576 Features |= F;
1577 }
1578 return Features;
1579}
1580
1581std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,
1582 SanitizerMask Mask) {
1583 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
1584 E = Args.rend();
1585 I != E; ++I) {
1586 const auto *Arg = *I;
1587 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
1588 SanitizerMask AddKinds =
1590 if (AddKinds & Mask)
1591 return describeSanitizeArg(Arg, Mask);
1592 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
1593 SanitizerMask RemoveKinds =
1595 Mask &= ~RemoveKinds;
1596 }
1597 }
1598 llvm_unreachable("arg list didn't provide expected value");
1599}
1600
1601std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask) {
1602 assert(A->getOption().matches(options::OPT_fsanitize_EQ) &&
1603 "Invalid argument in describeSanitizerArg!");
1604
1605 std::string Sanitizers;
1606 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1608 parseSanitizerValue(A->getValue(i), /*AllowGroups=*/true)) &
1609 Mask) {
1610 if (!Sanitizers.empty())
1611 Sanitizers += ",";
1612 Sanitizers += A->getValue(i);
1613 }
1614 }
1615
1616 assert(!Sanitizers.empty() && "arg didn't provide expected value");
1617 return "-fsanitize=" + Sanitizers;
1618}
const Decl * D
IndirectLocalPath & Path
Expr * E
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)
BinaryMetadataFeature
@ BinaryMetadataUAR
@ BinaryMetadataCovered
@ BinaryMetadataAtomics
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 std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static const SanitizerMask NeedsUbsanCxxRt
static const SanitizerMask TrappingDefault
static const SanitizerMask CompatibleWithMinimalRuntime
static const SanitizerMask Unrecoverable
static const SanitizerMask RecoverableByDefault
static const SanitizerMask NeedsLTO
static SanitizerMask setGroupBits(SanitizerMask Kinds)
Sets group bits for every group that has at least one representative already enabled in Kinds.
static const SanitizerMask NeedsUbsanRt
static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A, bool DiagnoseErrors)
Parse -f(no-)?sanitize-coverage= flag values, diagnosing any invalid components.
static void validateSpecialCaseListFormat(const Driver &D, std::vector< std::string > &SCLFiles, unsigned MalformedSCLErrorDiagID, bool DiagnoseErrors)
static const SanitizerMask NotAllowedWithTrap
static void parseSpecialCaseListArg(const Driver &D, const llvm::opt::ArgList &Args, std::vector< std::string > &SCLFiles, llvm::opt::OptSpecifier SCLOptionID, llvm::opt::OptSpecifier NoSCLOptionID, unsigned MalformedSCLErrorDiagID, bool DiagnoseErrors)
Parse -f(no-)?sanitize-(coverage-)?(allow|ignore)list argument's values, diagnosing any invalid file ...
static 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
CoverageFeature
@ CoverageTracePCGuard
@ CoverageTraceLoads
@ CoverageTracePC
@ CoverageFunc
@ Coverage8bitCounters
@ CoverageTraceCmp
@ CoverageBB
@ CoverageTraceDiv
@ CoverageInlineBoolFlag
@ CoverageTraceStores
@ CoverageTraceGep
@ CoverageStackDepth
@ CoverageControlFlow
@ CoverageNoPrune
@ CoveragePCTable
@ CoverageIndirCall
@ CoverageInline8bitCounters
@ CoverageTraceBB
@ CoverageEdge
Defines the clang::SanitizerKind enum.
@ None
Don't exclude any overflow patterns from sanitizers.
Definition: LangOptions.h:385
@ AddUnsignedOverflowTest
if (a + b < a)
Definition: LangOptions.h:391
@ All
Exclude all overflow patterns (below)
Definition: LangOptions.h:387
@ AddSignedOverflowTest
if (a + b < a)
Definition: LangOptions.h:389
@ PostDecrInWhile
while (count–)
Definition: LangOptions.h:395
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition: Driver.h:77
DiagnosticBuilder Diag(unsigned DiagID) const
Definition: Driver.h:144
SanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, bool DiagnoseErrors=true)
Parses the sanitizer arguments from an argument list.
void addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, types::ID InputType) const
ToolChain - Access to tools for a single platform.
Definition: ToolChain.h:92
const Driver & getDriver() const
Definition: ToolChain.h:252
RTTIMode getRTTIMode() const
Definition: ToolChain.h:326
const llvm::opt::Arg * getRTTIArg() const
Definition: ToolChain.h:323
const llvm::Triple & getTriple() const
Definition: ToolChain.h:254
virtual SanitizerMask getSupportedSanitizers() const
Return sanitizers which are available in this toolchain.
Definition: ToolChain.cpp:1456
std::string getCompilerRTBasename(const llvm::opt::ArgList &Args, StringRef Component, FileType Type=ToolChain::FT_Static) const
Definition: ToolChain.cpp:713
virtual SanitizerMask getDefaultSanitizers() const
Return sanitizers which are enabled by default.
Definition: ToolChain.h:786
bool isCXX(ID Id)
isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers).
Definition: Types.cpp:231
The JSON file list parser is used to communicate input to InstallAPI.
StringRef AsanDtorKindToString(llvm::AsanDtorKind kind)
Definition: Sanitizers.cpp:72
SanitizerMask expandSanitizerGroups(SanitizerMask Kinds)
For each sanitizer group bit set in Kinds, set the bits for sanitizers this group enables.
Definition: Sanitizers.cpp:47
SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups)
Parse a single value from a -fsanitize= or -fno-sanitize= value list.
Definition: Sanitizers.cpp:29
llvm::AsanDtorKind AsanDtorKindFromString(StringRef kind)
Definition: Sanitizers.cpp:84
llvm::AsanDetectStackUseAfterReturnMode AsanDetectStackUseAfterReturnModeFromString(StringRef modeStr)
Definition: Sanitizers.cpp:107
StringRef AsanDetectStackUseAfterReturnModeToString(llvm::AsanDetectStackUseAfterReturnMode mode)
Definition: Sanitizers.cpp:91
bool empty() const
Returns true if no sanitizers are enabled.
Definition: Sanitizers.h:179
bool has(SanitizerMask K) const
Check if a certain (single) sanitizer is enabled.
Definition: Sanitizers.h:159
SanitizerMask Mask
Bitmask of enabled sanitizers.
Definition: Sanitizers.h:182
bool hasOneOf(SanitizerMask K) const
Check if one or more sanitizers are enabled.
Definition: Sanitizers.h:165