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