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