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