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