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 // -fsanitize=undefined does not expand to signed-integer-overflow in
491 // -fwrapv (implied by -fno-strict-overflow) mode.
492 if (Add & SanitizerKind::UndefinedGroup) {
493 bool S = Args.hasFlagNoClaim(options::OPT_fno_strict_overflow,
494 options::OPT_fstrict_overflow, false);
495 if (Args.hasFlagNoClaim(options::OPT_fwrapv, options::OPT_fno_wrapv, S))
496 Add &= ~SanitizerKind::SignedIntegerOverflow;
497 }
498 Add &= Supported;
499
500 if (Add & SanitizerKind::Fuzzer)
501 Add |= SanitizerKind::FuzzerNoLink;
502
503 // Enable coverage if the fuzzing flag is set.
504 if (Add & SanitizerKind::FuzzerNoLink) {
505 CoverageFeatures |= CoverageInline8bitCounters | CoverageIndirCall |
507 // Due to TLS differences, stack depth tracking is only enabled on Linux
508 if (TC.getTriple().isOSLinux())
509 CoverageFeatures |= CoverageStackDepth;
510 }
511
512 Kinds |= Add;
513 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
514 Arg->claim();
515 SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors);
516 AllRemove |= expandSanitizerGroups(Remove);
517 }
518 }
519
520 std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
521 std::make_pair(SanitizerKind::Address,
522 SanitizerKind::Thread | SanitizerKind::Memory),
523 std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory),
524 std::make_pair(SanitizerKind::Leak,
525 SanitizerKind::Thread | SanitizerKind::Memory),
526 std::make_pair(SanitizerKind::KernelAddress,
527 SanitizerKind::Address | SanitizerKind::Leak |
528 SanitizerKind::Thread | SanitizerKind::Memory),
529 std::make_pair(SanitizerKind::HWAddress,
530 SanitizerKind::Address | SanitizerKind::Thread |
531 SanitizerKind::Memory | SanitizerKind::KernelAddress),
532 std::make_pair(SanitizerKind::Scudo,
533 SanitizerKind::Address | SanitizerKind::HWAddress |
534 SanitizerKind::Leak | SanitizerKind::Thread |
535 SanitizerKind::Memory | SanitizerKind::KernelAddress),
536 std::make_pair(SanitizerKind::SafeStack,
537 (TC.getTriple().isOSFuchsia() ? SanitizerMask()
538 : SanitizerKind::Leak) |
539 SanitizerKind::Address | SanitizerKind::HWAddress |
540 SanitizerKind::Thread | SanitizerKind::Memory |
541 SanitizerKind::KernelAddress),
542 std::make_pair(SanitizerKind::KernelHWAddress,
543 SanitizerKind::Address | SanitizerKind::HWAddress |
544 SanitizerKind::Leak | SanitizerKind::Thread |
545 SanitizerKind::Memory | SanitizerKind::KernelAddress |
546 SanitizerKind::SafeStack),
547 std::make_pair(SanitizerKind::KernelMemory,
548 SanitizerKind::Address | SanitizerKind::HWAddress |
549 SanitizerKind::Leak | SanitizerKind::Thread |
550 SanitizerKind::Memory | SanitizerKind::KernelAddress |
551 SanitizerKind::Scudo | SanitizerKind::SafeStack),
552 std::make_pair(SanitizerKind::MemTag,
553 SanitizerKind::Address | SanitizerKind::KernelAddress |
554 SanitizerKind::HWAddress |
555 SanitizerKind::KernelHWAddress),
556 std::make_pair(SanitizerKind::KCFI, SanitizerKind::Function)};
557 // Enable toolchain specific default sanitizers if not explicitly disabled.
558 SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove;
559
560 // Disable default sanitizers that are incompatible with explicitly requested
561 // ones.
562 for (auto G : IncompatibleGroups) {
563 SanitizerMask Group = G.first;
564 if ((Default & Group) && (Kinds & G.second))
565 Default &= ~Group;
566 }
567
568 Kinds |= Default;
569
570 // We disable the vptr sanitizer if it was enabled by group expansion but RTTI
571 // is disabled.
572 if ((Kinds & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {
573 Kinds &= ~SanitizerKind::Vptr;
574 }
575
576 // Check that LTO is enabled if we need it.
577 if ((Kinds & NeedsLTO) && !D.isUsingLTO() && DiagnoseErrors) {
578 D.Diag(diag::err_drv_argument_only_allowed_with)
579 << lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto";
580 }
581
582 if ((Kinds & SanitizerKind::ShadowCallStack) && TC.getTriple().isAArch64() &&
583 !llvm::AArch64::isX18ReservedByDefault(TC.getTriple()) &&
584 !Args.hasArg(options::OPT_ffixed_x18) && DiagnoseErrors) {
585 D.Diag(diag::err_drv_argument_only_allowed_with)
586 << lastArgumentForMask(D, Args, Kinds & SanitizerKind::ShadowCallStack)
587 << "-ffixed-x18";
588 }
589
590 // Report error if there are non-trapping sanitizers that require
591 // c++abi-specific parts of UBSan runtime, and they are not provided by the
592 // toolchain. We don't have a good way to check the latter, so we just
593 // check if the toolchan supports vptr.
594 if (~Supported & SanitizerKind::Vptr) {
595 SanitizerMask KindsToDiagnose = Kinds & ~TrappingKinds & NeedsUbsanCxxRt;
596 // The runtime library supports the Microsoft C++ ABI, but only well enough
597 // for CFI. FIXME: Remove this once we support vptr on Windows.
598 if (TC.getTriple().isOSWindows())
599 KindsToDiagnose &= ~SanitizerKind::CFI;
600 if (KindsToDiagnose) {
601 SanitizerSet S;
602 S.Mask = KindsToDiagnose;
603 if (DiagnoseErrors)
604 D.Diag(diag::err_drv_unsupported_opt_for_target)
605 << ("-fno-sanitize-trap=" + toString(S)) << TC.getTriple().str();
606 Kinds &= ~KindsToDiagnose;
607 }
608 }
609
610 // Warn about incompatible groups of sanitizers.
611 for (auto G : IncompatibleGroups) {
612 SanitizerMask Group = G.first;
613 if (Kinds & Group) {
614 if (SanitizerMask Incompatible = Kinds & G.second) {
615 if (DiagnoseErrors)
616 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
617 << lastArgumentForMask(D, Args, Group)
618 << lastArgumentForMask(D, Args, Incompatible);
619 Kinds &= ~Incompatible;
620 }
621 }
622 }
623 // FIXME: Currently -fsanitize=leak is silently ignored in the presence of
624 // -fsanitize=address. Perhaps it should print an error, or perhaps
625 // -f(-no)sanitize=leak should change whether leak detection is enabled by
626 // default in ASan?
627
628 // Parse -f(no-)?sanitize-recover flags.
630 SanitizerMask DiagnosedUnrecoverableKinds;
631 SanitizerMask DiagnosedAlwaysRecoverableKinds;
632 for (const auto *Arg : Args) {
633 if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
634 SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors);
635 // Report error if user explicitly tries to recover from unrecoverable
636 // sanitizer.
637 if (SanitizerMask KindsToDiagnose =
638 Add & Unrecoverable & ~DiagnosedUnrecoverableKinds) {
639 SanitizerSet SetToDiagnose;
640 SetToDiagnose.Mask |= KindsToDiagnose;
641 if (DiagnoseErrors)
642 D.Diag(diag::err_drv_unsupported_option_argument)
643 << Arg->getSpelling() << toString(SetToDiagnose);
644 DiagnosedUnrecoverableKinds |= KindsToDiagnose;
645 }
646 RecoverableKinds |= expandSanitizerGroups(Add);
647 Arg->claim();
648 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {
649 SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors);
650 // Report error if user explicitly tries to disable recovery from
651 // always recoverable sanitizer.
652 if (SanitizerMask KindsToDiagnose =
653 Remove & AlwaysRecoverable & ~DiagnosedAlwaysRecoverableKinds) {
654 SanitizerSet SetToDiagnose;
655 SetToDiagnose.Mask |= KindsToDiagnose;
656 if (DiagnoseErrors)
657 D.Diag(diag::err_drv_unsupported_option_argument)
658 << Arg->getSpelling() << toString(SetToDiagnose);
659 DiagnosedAlwaysRecoverableKinds |= KindsToDiagnose;
660 }
661 RecoverableKinds &= ~expandSanitizerGroups(Remove);
662 Arg->claim();
663 }
664 }
665 RecoverableKinds &= Kinds;
666 RecoverableKinds &= ~Unrecoverable;
667
668 TrappingKinds &= Kinds;
669 RecoverableKinds &= ~TrappingKinds;
670
671 // Setup ignorelist files.
672 // Add default ignorelist from resource directory for activated sanitizers,
673 // and validate special case lists format.
674 if (!Args.hasArgNoClaim(options::OPT_fno_sanitize_ignorelist))
675 addDefaultIgnorelists(D, Kinds, SystemIgnorelistFiles, DiagnoseErrors);
676
677 // Parse -f(no-)?sanitize-ignorelist options.
678 // This also validates special case lists format.
680 D, Args, UserIgnorelistFiles, options::OPT_fsanitize_ignorelist_EQ,
681 options::OPT_fno_sanitize_ignorelist,
682 clang::diag::err_drv_malformed_sanitizer_ignorelist, DiagnoseErrors);
683
684 // Parse -f[no-]sanitize-memory-track-origins[=level] options.
685 if (AllAddedKinds & SanitizerKind::Memory) {
686 if (Arg *A =
687 Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
688 options::OPT_fno_sanitize_memory_track_origins)) {
689 if (!A->getOption().matches(
690 options::OPT_fno_sanitize_memory_track_origins)) {
691 StringRef S = A->getValue();
692 if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
693 MsanTrackOrigins > 2) {
694 if (DiagnoseErrors)
695 D.Diag(clang::diag::err_drv_invalid_value)
696 << A->getAsString(Args) << S;
697 }
698 }
699 }
700 MsanUseAfterDtor = Args.hasFlag(
701 options::OPT_fsanitize_memory_use_after_dtor,
702 options::OPT_fno_sanitize_memory_use_after_dtor, MsanUseAfterDtor);
703 MsanParamRetval = Args.hasFlag(
704 options::OPT_fsanitize_memory_param_retval,
705 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
706 } else if (AllAddedKinds & SanitizerKind::KernelMemory) {
707 MsanUseAfterDtor = false;
708 MsanParamRetval = Args.hasFlag(
709 options::OPT_fsanitize_memory_param_retval,
710 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
711 } else {
712 MsanUseAfterDtor = false;
713 MsanParamRetval = false;
714 }
715
716 if (AllAddedKinds & SanitizerKind::MemTag) {
717 StringRef S =
718 Args.getLastArgValue(options::OPT_fsanitize_memtag_mode_EQ, "sync");
719 if (S == "async" || S == "sync") {
720 MemtagMode = S.str();
721 } else {
722 D.Diag(clang::diag::err_drv_invalid_value_with_suggestion)
723 << "-fsanitize-memtag-mode=" << S << "{async, sync}";
724 MemtagMode = "sync";
725 }
726 }
727
728 if (AllAddedKinds & SanitizerKind::Thread) {
729 TsanMemoryAccess = Args.hasFlag(
730 options::OPT_fsanitize_thread_memory_access,
731 options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess);
732 TsanFuncEntryExit = Args.hasFlag(
733 options::OPT_fsanitize_thread_func_entry_exit,
734 options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit);
735 TsanAtomics =
736 Args.hasFlag(options::OPT_fsanitize_thread_atomics,
737 options::OPT_fno_sanitize_thread_atomics, TsanAtomics);
738 }
739
740 if (AllAddedKinds & SanitizerKind::CFI) {
741 // Without PIE, external function address may resolve to a PLT record, which
742 // can not be verified by the target module.
743 NeedPIE |= CfiCrossDso;
744 CfiICallGeneralizePointers =
745 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
746
747 CfiICallNormalizeIntegers =
748 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
749
750 if (CfiCrossDso && CfiICallGeneralizePointers && DiagnoseErrors)
751 D.Diag(diag::err_drv_argument_not_allowed_with)
752 << "-fsanitize-cfi-cross-dso"
753 << "-fsanitize-cfi-icall-generalize-pointers";
754
755 CfiCanonicalJumpTables =
756 Args.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables,
757 options::OPT_fno_sanitize_cfi_canonical_jump_tables, true);
758 }
759
760 if (AllAddedKinds & SanitizerKind::KCFI) {
761 CfiICallNormalizeIntegers =
762 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
763
764 if (AllAddedKinds & SanitizerKind::CFI && DiagnoseErrors)
765 D.Diag(diag::err_drv_argument_not_allowed_with)
766 << "-fsanitize=kcfi"
767 << lastArgumentForMask(D, Args, SanitizerKind::CFI);
768 }
769
770 Stats = Args.hasFlag(options::OPT_fsanitize_stats,
771 options::OPT_fno_sanitize_stats, false);
772
773 if (MinimalRuntime) {
774 SanitizerMask IncompatibleMask =
775 Kinds & ~setGroupBits(CompatibleWithMinimalRuntime);
776 if (IncompatibleMask && DiagnoseErrors)
777 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
778 << "-fsanitize-minimal-runtime"
779 << lastArgumentForMask(D, Args, IncompatibleMask);
780
781 SanitizerMask NonTrappingCfi = Kinds & SanitizerKind::CFI & ~TrappingKinds;
782 if (NonTrappingCfi && DiagnoseErrors)
783 D.Diag(clang::diag::err_drv_argument_only_allowed_with)
784 << "fsanitize-minimal-runtime"
785 << "fsanitize-trap=cfi";
786 }
787
788 // Parse -f(no-)?sanitize-coverage flags if coverage is supported by the
789 // enabled sanitizers.
790 for (const auto *Arg : Args) {
791 if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
792 int LegacySanitizeCoverage;
793 if (Arg->getNumValues() == 1 &&
794 !StringRef(Arg->getValue(0))
795 .getAsInteger(0, LegacySanitizeCoverage)) {
796 CoverageFeatures = 0;
797 Arg->claim();
798 if (LegacySanitizeCoverage != 0 && DiagnoseErrors) {
799 D.Diag(diag::warn_drv_deprecated_arg)
800 << Arg->getAsString(Args) << "-fsanitize-coverage=trace-pc-guard";
801 }
802 continue;
803 }
804 CoverageFeatures |= parseCoverageFeatures(D, Arg, DiagnoseErrors);
805
806 // Disable coverage and not claim the flags if there is at least one
807 // non-supporting sanitizer.
808 if (!(AllAddedKinds & ~AllRemove & ~setGroupBits(SupportsCoverage))) {
809 Arg->claim();
810 } else {
811 CoverageFeatures = 0;
812 }
813 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
814 Arg->claim();
815 CoverageFeatures &= ~parseCoverageFeatures(D, Arg, DiagnoseErrors);
816 }
817 }
818 // Choose at most one coverage type: function, bb, or edge.
819 if (DiagnoseErrors) {
820 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageBB))
821 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
822 << "-fsanitize-coverage=func"
823 << "-fsanitize-coverage=bb";
824 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageEdge))
825 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
826 << "-fsanitize-coverage=func"
827 << "-fsanitize-coverage=edge";
828 if ((CoverageFeatures & CoverageBB) && (CoverageFeatures & CoverageEdge))
829 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
830 << "-fsanitize-coverage=bb"
831 << "-fsanitize-coverage=edge";
832 // Basic block tracing and 8-bit counters require some type of coverage
833 // enabled.
834 if (CoverageFeatures & CoverageTraceBB)
835 D.Diag(clang::diag::warn_drv_deprecated_arg)
836 << "-fsanitize-coverage=trace-bb"
837 << "-fsanitize-coverage=trace-pc-guard";
838 if (CoverageFeatures & Coverage8bitCounters)
839 D.Diag(clang::diag::warn_drv_deprecated_arg)
840 << "-fsanitize-coverage=8bit-counters"
841 << "-fsanitize-coverage=trace-pc-guard";
842 }
843
844 int InsertionPointTypes = CoverageFunc | CoverageBB | CoverageEdge;
845 int InstrumentationTypes = CoverageTracePC | CoverageTracePCGuard |
849 if ((CoverageFeatures & InsertionPointTypes) &&
850 !(CoverageFeatures & InstrumentationTypes) && DiagnoseErrors) {
851 D.Diag(clang::diag::warn_drv_deprecated_arg)
852 << "-fsanitize-coverage=[func|bb|edge]"
853 << "-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc],["
854 "control-flow]";
855 }
856
857 // trace-pc w/o func/bb/edge implies edge.
858 if (!(CoverageFeatures & InsertionPointTypes)) {
859 if (CoverageFeatures &
862 CoverageFeatures |= CoverageEdge;
863
864 if (CoverageFeatures & CoverageStackDepth)
865 CoverageFeatures |= CoverageFunc;
866 }
867
868 // Parse -fsanitize-coverage-(allow|ignore)list options if coverage enabled.
869 // This also validates special case lists format.
870 // Here, OptSpecifier() acts as a never-matching command-line argument.
871 // So, there is no way to clear coverage lists but you can append to them.
872 if (CoverageFeatures) {
874 D, Args, CoverageAllowlistFiles,
875 options::OPT_fsanitize_coverage_allowlist, OptSpecifier(),
876 clang::diag::err_drv_malformed_sanitizer_coverage_allowlist,
877 DiagnoseErrors);
879 D, Args, CoverageIgnorelistFiles,
880 options::OPT_fsanitize_coverage_ignorelist, OptSpecifier(),
881 clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist,
882 DiagnoseErrors);
883 }
884
885 // Parse -f(no-)?sanitize-metadata.
886 for (const auto *Arg :
887 Args.filtered(options::OPT_fexperimental_sanitize_metadata_EQ,
888 options::OPT_fno_experimental_sanitize_metadata_EQ)) {
889 if (Arg->getOption().matches(
890 options::OPT_fexperimental_sanitize_metadata_EQ)) {
891 Arg->claim();
892 BinaryMetadataFeatures |=
893 parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);
894 } else {
895 Arg->claim();
896 BinaryMetadataFeatures &=
897 ~parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);
898 }
899 }
900
901 // Parse -fsanitize-metadata-ignorelist option if enabled.
902 if (BinaryMetadataFeatures) {
904 D, Args, BinaryMetadataIgnorelistFiles,
905 options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ,
906 OptSpecifier(), // Cannot clear ignore list, only append.
907 clang::diag::err_drv_malformed_sanitizer_metadata_ignorelist,
908 DiagnoseErrors);
909 }
910
911 SharedRuntime =
912 Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan,
913 TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() ||
914 TC.getTriple().isOSDarwin());
915
916 ImplicitCfiRuntime = TC.getTriple().isAndroid();
917
918 if (AllAddedKinds & SanitizerKind::Address) {
919 NeedPIE |= TC.getTriple().isOSFuchsia();
920 if (Arg *A =
921 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
922 StringRef S = A->getValue();
923 // Legal values are 0 and 1, 2, but in future we may add more levels.
924 if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
925 AsanFieldPadding > 2) &&
926 DiagnoseErrors) {
927 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
928 }
929 }
930
931 if (Arg *WindowsDebugRTArg =
932 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
933 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
934 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
935 switch (WindowsDebugRTArg->getOption().getID()) {
936 case options::OPT__SLASH_MTd:
937 case options::OPT__SLASH_MDd:
938 case options::OPT__SLASH_LDd:
939 if (DiagnoseErrors) {
940 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
941 << WindowsDebugRTArg->getAsString(Args)
942 << lastArgumentForMask(D, Args, SanitizerKind::Address);
943 D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
944 }
945 }
946 }
947
948 StableABI = Args.hasFlag(options::OPT_fsanitize_stable_abi,
949 options::OPT_fno_sanitize_stable_abi, false);
950
951 AsanUseAfterScope = Args.hasFlag(
952 options::OPT_fsanitize_address_use_after_scope,
953 options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);
954
955 AsanPoisonCustomArrayCookie = Args.hasFlag(
956 options::OPT_fsanitize_address_poison_custom_array_cookie,
957 options::OPT_fno_sanitize_address_poison_custom_array_cookie,
958 AsanPoisonCustomArrayCookie);
959
960 AsanOutlineInstrumentation =
961 Args.hasFlag(options::OPT_fsanitize_address_outline_instrumentation,
962 options::OPT_fno_sanitize_address_outline_instrumentation,
963 AsanOutlineInstrumentation);
964
965 AsanGlobalsDeadStripping = Args.hasFlag(
966 options::OPT_fsanitize_address_globals_dead_stripping,
967 options::OPT_fno_sanitize_address_globals_dead_stripping, true);
968
969 // Enable ODR indicators which allow better handling of mixed instrumented
970 // and uninstrumented globals. Disable them for Windows where weak odr
971 // indicators (.weak.__odr_asan_gen*) may cause multiple definition linker
972 // errors in the absence of -lldmingw.
973 AsanUseOdrIndicator =
974 Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
975 options::OPT_fno_sanitize_address_use_odr_indicator,
976 !TC.getTriple().isOSWindows());
977
978 if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) {
979 AsanInvalidPointerCmp = true;
980 }
981
982 if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) {
983 AsanInvalidPointerSub = true;
984 }
985
986 if (TC.getTriple().isOSDarwin() &&
987 (Args.hasArg(options::OPT_mkernel) ||
988 Args.hasArg(options::OPT_fapple_kext))) {
989 AsanDtorKind = llvm::AsanDtorKind::None;
990 }
991
992 if (const auto *Arg =
993 Args.getLastArg(options::OPT_sanitize_address_destructor_EQ)) {
994 auto parsedAsanDtorKind = AsanDtorKindFromString(Arg->getValue());
995 if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid && DiagnoseErrors) {
996 TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)
997 << Arg->getSpelling() << Arg->getValue();
998 }
999 AsanDtorKind = parsedAsanDtorKind;
1000 }
1001
1002 if (const auto *Arg = Args.getLastArg(
1003 options::OPT_sanitize_address_use_after_return_EQ)) {
1004 auto parsedAsanUseAfterReturn =
1006 if (parsedAsanUseAfterReturn ==
1007 llvm::AsanDetectStackUseAfterReturnMode::Invalid &&
1008 DiagnoseErrors) {
1009 TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)
1010 << Arg->getSpelling() << Arg->getValue();
1011 }
1012 AsanUseAfterReturn = parsedAsanUseAfterReturn;
1013 }
1014
1015 } else {
1016 AsanUseAfterScope = false;
1017 // -fsanitize=pointer-compare/pointer-subtract requires -fsanitize=address.
1018 SanitizerMask DetectInvalidPointerPairs =
1019 SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract;
1020 if ((AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) &&
1021 DiagnoseErrors) {
1022 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)
1023 << lastArgumentForMask(D, Args,
1024 SanitizerKind::PointerCompare |
1025 SanitizerKind::PointerSubtract)
1026 << "-fsanitize=address";
1027 }
1028 }
1029
1030 if (AllAddedKinds & SanitizerKind::HWAddress) {
1031 if (Arg *HwasanAbiArg =
1032 Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {
1033 HwasanAbi = HwasanAbiArg->getValue();
1034 if (HwasanAbi != "platform" && HwasanAbi != "interceptor" &&
1035 DiagnoseErrors)
1036 D.Diag(clang::diag::err_drv_invalid_value)
1037 << HwasanAbiArg->getAsString(Args) << HwasanAbi;
1038 } else {
1039 HwasanAbi = "interceptor";
1040 }
1041 if (TC.getTriple().getArch() == llvm::Triple::x86_64)
1042 HwasanUseAliases = Args.hasFlag(
1043 options::OPT_fsanitize_hwaddress_experimental_aliasing,
1044 options::OPT_fno_sanitize_hwaddress_experimental_aliasing,
1045 HwasanUseAliases);
1046 }
1047
1048 if (AllAddedKinds & SanitizerKind::SafeStack) {
1049 // SafeStack runtime is built into the system on Android and Fuchsia.
1050 SafeStackRuntime =
1051 !TC.getTriple().isAndroid() && !TC.getTriple().isOSFuchsia();
1052 }
1053
1054 LinkRuntimes =
1055 Args.hasFlag(options::OPT_fsanitize_link_runtime,
1056 options::OPT_fno_sanitize_link_runtime, LinkRuntimes);
1057
1058 // Parse -link-cxx-sanitizer flag.
1059 LinkCXXRuntimes = Args.hasArg(options::OPT_fsanitize_link_cxx_runtime,
1060 options::OPT_fno_sanitize_link_cxx_runtime,
1061 LinkCXXRuntimes) ||
1062 D.CCCIsCXX();
1063
1064 NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile,
1065 options::OPT_fmemory_profile_EQ,
1066 options::OPT_fno_memory_profile, false);
1067
1068 // Finally, initialize the set of available and recoverable sanitizers.
1069 Sanitizers.Mask |= Kinds;
1070 RecoverableSanitizers.Mask |= RecoverableKinds;
1071 TrapSanitizers.Mask |= TrappingKinds;
1072 assert(!(RecoverableKinds & TrappingKinds) &&
1073 "Overlap between recoverable and trapping sanitizers");
1074}
1075
1076static std::string toString(const clang::SanitizerSet &Sanitizers) {
1077 std::string Res;
1078#define SANITIZER(NAME, ID) \
1079 if (Sanitizers.has(SanitizerKind::ID)) { \
1080 if (!Res.empty()) \
1081 Res += ","; \
1082 Res += NAME; \
1083 }
1084#include "clang/Basic/Sanitizers.def"
1085 return Res;
1086}
1087
1088static void addSpecialCaseListOpt(const llvm::opt::ArgList &Args,
1089 llvm::opt::ArgStringList &CmdArgs,
1090 const char *SCLOptFlag,
1091 const std::vector<std::string> &SCLFiles) {
1092 for (const auto &SCLPath : SCLFiles) {
1093 SmallString<64> SCLOpt(SCLOptFlag);
1094 SCLOpt += SCLPath;
1095 CmdArgs.push_back(Args.MakeArgString(SCLOpt));
1096 }
1097}
1098
1099static void addIncludeLinkerOption(const ToolChain &TC,
1100 const llvm::opt::ArgList &Args,
1101 llvm::opt::ArgStringList &CmdArgs,
1102 StringRef SymbolName) {
1103 SmallString<64> LinkerOptionFlag;
1104 LinkerOptionFlag = "--linker-option=/include:";
1105 if (TC.getTriple().getArch() == llvm::Triple::x86) {
1106 // Win32 mangles C function names with a '_' prefix.
1107 LinkerOptionFlag += '_';
1108 }
1109 LinkerOptionFlag += SymbolName;
1110 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
1111}
1112
1113static bool hasTargetFeatureMTE(const llvm::opt::ArgStringList &CmdArgs) {
1114 for (auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End;
1115 ++Start) {
1116 auto It = std::find(Start, End, StringRef("+mte"));
1117 if (It == End)
1118 break;
1119 if (It > Start && *std::prev(It) == StringRef("-target-feature"))
1120 return true;
1121 Start = It;
1122 }
1123 return false;
1124}
1125
1126void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
1127 llvm::opt::ArgStringList &CmdArgs,
1128 types::ID InputType) const {
1129 // NVPTX doesn't currently support sanitizers. Bailing out here means
1130 // that e.g. -fsanitize=address applies only to host code, which is what we
1131 // want for now.
1132 if (TC.getTriple().isNVPTX())
1133 return;
1134 // AMDGPU sanitizer support is experimental and controlled by -fgpu-sanitize.
1135 bool GPUSanitize = false;
1136 if (TC.getTriple().isAMDGPU()) {
1137 if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
1138 true))
1139 return;
1140 GPUSanitize = true;
1141 }
1142
1143 // Translate available CoverageFeatures to corresponding clang-cc1 flags.
1144 // Do it even if Sanitizers.empty() since some forms of coverage don't require
1145 // sanitizers.
1146 std::pair<int, const char *> CoverageFlags[] = {
1147 std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"),
1148 std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"),
1149 std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"),
1150 std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"),
1151 std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"),
1152 std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"),
1153 std::make_pair(CoverageTraceDiv, "-fsanitize-coverage-trace-div"),
1154 std::make_pair(CoverageTraceGep, "-fsanitize-coverage-trace-gep"),
1155 std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"),
1156 std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"),
1157 std::make_pair(CoverageTracePCGuard,
1158 "-fsanitize-coverage-trace-pc-guard"),
1159 std::make_pair(CoverageInline8bitCounters,
1160 "-fsanitize-coverage-inline-8bit-counters"),
1161 std::make_pair(CoverageInlineBoolFlag,
1162 "-fsanitize-coverage-inline-bool-flag"),
1163 std::make_pair(CoveragePCTable, "-fsanitize-coverage-pc-table"),
1164 std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune"),
1165 std::make_pair(CoverageStackDepth, "-fsanitize-coverage-stack-depth"),
1166 std::make_pair(CoverageTraceLoads, "-fsanitize-coverage-trace-loads"),
1167 std::make_pair(CoverageTraceStores, "-fsanitize-coverage-trace-stores"),
1168 std::make_pair(CoverageControlFlow, "-fsanitize-coverage-control-flow")};
1169 for (auto F : CoverageFlags) {
1170 if (CoverageFeatures & F.first)
1171 CmdArgs.push_back(F.second);
1172 }
1174 Args, CmdArgs, "-fsanitize-coverage-allowlist=", CoverageAllowlistFiles);
1175 addSpecialCaseListOpt(Args, CmdArgs, "-fsanitize-coverage-ignorelist=",
1176 CoverageIgnorelistFiles);
1177
1178 if (!GPUSanitize) {
1179 // Translate available BinaryMetadataFeatures to corresponding clang-cc1
1180 // flags. Does not depend on any other sanitizers. Unsupported on GPUs.
1181 const std::pair<int, std::string> BinaryMetadataFlags[] = {
1182 std::make_pair(BinaryMetadataCovered, "covered"),
1183 std::make_pair(BinaryMetadataAtomics, "atomics"),
1184 std::make_pair(BinaryMetadataUAR, "uar")};
1185 for (const auto &F : BinaryMetadataFlags) {
1186 if (BinaryMetadataFeatures & F.first)
1187 CmdArgs.push_back(
1188 Args.MakeArgString("-fexperimental-sanitize-metadata=" + F.second));
1189 }
1190 addSpecialCaseListOpt(Args, CmdArgs,
1191 "-fexperimental-sanitize-metadata-ignorelist=",
1192 BinaryMetadataIgnorelistFiles);
1193 }
1194
1195 if (TC.getTriple().isOSWindows() && needsUbsanRt()) {
1196 // Instruct the code generator to embed linker directives in the object file
1197 // that cause the required runtime libraries to be linked.
1198 CmdArgs.push_back(
1199 Args.MakeArgString("--dependent-lib=" +
1200 TC.getCompilerRTBasename(Args, "ubsan_standalone")));
1201 if (types::isCXX(InputType))
1202 CmdArgs.push_back(Args.MakeArgString(
1203 "--dependent-lib=" +
1204 TC.getCompilerRTBasename(Args, "ubsan_standalone_cxx")));
1205 }
1206 if (TC.getTriple().isOSWindows() && needsStatsRt()) {
1207 CmdArgs.push_back(Args.MakeArgString(
1208 "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats_client")));
1209
1210 // The main executable must export the stats runtime.
1211 // FIXME: Only exporting from the main executable (e.g. based on whether the
1212 // translation unit defines main()) would save a little space, but having
1213 // multiple copies of the runtime shouldn't hurt.
1214 CmdArgs.push_back(Args.MakeArgString(
1215 "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats")));
1216 addIncludeLinkerOption(TC, Args, CmdArgs, "__sanitizer_stats_register");
1217 }
1218
1219 if (Sanitizers.empty())
1220 return;
1221 CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers)));
1222
1223 if (!RecoverableSanitizers.empty())
1224 CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" +
1225 toString(RecoverableSanitizers)));
1226
1227 if (!TrapSanitizers.empty())
1228 CmdArgs.push_back(
1229 Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));
1230
1231 addSpecialCaseListOpt(Args, CmdArgs,
1232 "-fsanitize-ignorelist=", UserIgnorelistFiles);
1233 addSpecialCaseListOpt(Args, CmdArgs,
1234 "-fsanitize-system-ignorelist=", SystemIgnorelistFiles);
1235
1236 if (MsanTrackOrigins)
1237 CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" +
1238 Twine(MsanTrackOrigins)));
1239
1240 if (MsanUseAfterDtor)
1241 CmdArgs.push_back("-fsanitize-memory-use-after-dtor");
1242
1243 if (!MsanParamRetval)
1244 CmdArgs.push_back("-fno-sanitize-memory-param-retval");
1245
1246 // FIXME: Pass these parameters as function attributes, not as -llvm flags.
1247 if (!TsanMemoryAccess) {
1248 CmdArgs.push_back("-mllvm");
1249 CmdArgs.push_back("-tsan-instrument-memory-accesses=0");
1250 CmdArgs.push_back("-mllvm");
1251 CmdArgs.push_back("-tsan-instrument-memintrinsics=0");
1252 }
1253 if (!TsanFuncEntryExit) {
1254 CmdArgs.push_back("-mllvm");
1255 CmdArgs.push_back("-tsan-instrument-func-entry-exit=0");
1256 }
1257 if (!TsanAtomics) {
1258 CmdArgs.push_back("-mllvm");
1259 CmdArgs.push_back("-tsan-instrument-atomics=0");
1260 }
1261
1262 if (HwasanUseAliases) {
1263 CmdArgs.push_back("-mllvm");
1264 CmdArgs.push_back("-hwasan-experimental-use-page-aliases=1");
1265 }
1266
1267 if (CfiCrossDso)
1268 CmdArgs.push_back("-fsanitize-cfi-cross-dso");
1269
1270 if (CfiICallGeneralizePointers)
1271 CmdArgs.push_back("-fsanitize-cfi-icall-generalize-pointers");
1272
1273 if (CfiICallNormalizeIntegers)
1274 CmdArgs.push_back("-fsanitize-cfi-icall-experimental-normalize-integers");
1275
1276 if (CfiCanonicalJumpTables)
1277 CmdArgs.push_back("-fsanitize-cfi-canonical-jump-tables");
1278
1279 if (Stats)
1280 CmdArgs.push_back("-fsanitize-stats");
1281
1282 if (MinimalRuntime)
1283 CmdArgs.push_back("-fsanitize-minimal-runtime");
1284
1285 if (AsanFieldPadding)
1286 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" +
1287 Twine(AsanFieldPadding)));
1288
1289 if (AsanUseAfterScope)
1290 CmdArgs.push_back("-fsanitize-address-use-after-scope");
1291
1292 if (AsanPoisonCustomArrayCookie)
1293 CmdArgs.push_back("-fsanitize-address-poison-custom-array-cookie");
1294
1295 if (AsanGlobalsDeadStripping)
1296 CmdArgs.push_back("-fsanitize-address-globals-dead-stripping");
1297
1298 if (!AsanUseOdrIndicator)
1299 CmdArgs.push_back("-fno-sanitize-address-use-odr-indicator");
1300
1301 if (AsanInvalidPointerCmp) {
1302 CmdArgs.push_back("-mllvm");
1303 CmdArgs.push_back("-asan-detect-invalid-pointer-cmp");
1304 }
1305
1306 if (AsanInvalidPointerSub) {
1307 CmdArgs.push_back("-mllvm");
1308 CmdArgs.push_back("-asan-detect-invalid-pointer-sub");
1309 }
1310
1311 if (AsanOutlineInstrumentation) {
1312 CmdArgs.push_back("-mllvm");
1313 CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");
1314 }
1315
1316 // When emitting Stable ABI instrumentation, force outlining calls and avoid
1317 // inlining shadow memory poisoning. While this is a big performance burden
1318 // for now it allows full abstraction from implementation details.
1319 if (StableABI) {
1320 CmdArgs.push_back("-mllvm");
1321 CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");
1322 CmdArgs.push_back("-mllvm");
1323 CmdArgs.push_back("-asan-max-inline-poisoning-size=0");
1324 CmdArgs.push_back("-mllvm");
1325 CmdArgs.push_back("-asan-guard-against-version-mismatch=0");
1326 }
1327
1328 // Only pass the option to the frontend if the user requested,
1329 // otherwise the frontend will just use the codegen default.
1330 if (AsanDtorKind != llvm::AsanDtorKind::Invalid) {
1331 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-destructor=" +
1332 AsanDtorKindToString(AsanDtorKind)));
1333 }
1334
1335 if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
1336 CmdArgs.push_back(Args.MakeArgString(
1337 "-fsanitize-address-use-after-return=" +
1338 AsanDetectStackUseAfterReturnModeToString(AsanUseAfterReturn)));
1339 }
1340
1341 if (!HwasanAbi.empty()) {
1342 CmdArgs.push_back("-default-function-attr");
1343 CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi));
1344 }
1345
1346 if (Sanitizers.has(SanitizerKind::HWAddress) && !HwasanUseAliases) {
1347 CmdArgs.push_back("-target-feature");
1348 CmdArgs.push_back("+tagged-globals");
1349 }
1350
1351 // MSan: Workaround for PR16386.
1352 // ASan: This is mainly to help LSan with cases such as
1353 // https://github.com/google/sanitizers/issues/373
1354 // We can't make this conditional on -fsanitize=leak, as that flag shouldn't
1355 // affect compilation.
1356 if (Sanitizers.has(SanitizerKind::Memory) ||
1357 Sanitizers.has(SanitizerKind::Address))
1358 CmdArgs.push_back("-fno-assume-sane-operator-new");
1359
1360 // libFuzzer wants to intercept calls to certain library functions, so the
1361 // following -fno-builtin-* flags force the compiler to emit interposable
1362 // libcalls to these functions. Other sanitizers effectively do the same thing
1363 // by marking all library call sites with NoBuiltin attribute in their LLVM
1364 // pass. (see llvm::maybeMarkSanitizerLibraryCallNoBuiltin)
1365 if (Sanitizers.has(SanitizerKind::FuzzerNoLink)) {
1366 CmdArgs.push_back("-fno-builtin-bcmp");
1367 CmdArgs.push_back("-fno-builtin-memcmp");
1368 CmdArgs.push_back("-fno-builtin-strncmp");
1369 CmdArgs.push_back("-fno-builtin-strcmp");
1370 CmdArgs.push_back("-fno-builtin-strncasecmp");
1371 CmdArgs.push_back("-fno-builtin-strcasecmp");
1372 CmdArgs.push_back("-fno-builtin-strstr");
1373 CmdArgs.push_back("-fno-builtin-strcasestr");
1374 CmdArgs.push_back("-fno-builtin-memmem");
1375 }
1376
1377 // Require -fvisibility= flag on non-Windows when compiling if vptr CFI is
1378 // enabled.
1379 if (Sanitizers.hasOneOf(CFIClasses) && !TC.getTriple().isOSWindows() &&
1380 !Args.hasArg(options::OPT_fvisibility_EQ)) {
1381 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)
1382 << lastArgumentForMask(TC.getDriver(), Args,
1383 Sanitizers.Mask & CFIClasses)
1384 << "-fvisibility=";
1385 }
1386
1387 if (Sanitizers.has(SanitizerKind::MemtagStack) &&
1388 !hasTargetFeatureMTE(CmdArgs))
1389 TC.getDriver().Diag(diag::err_stack_tagging_requires_hardware_feature);
1390}
1391
1392SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
1393 bool DiagnoseErrors) {
1394 assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
1395 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
1396 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
1397 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
1398 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
1399 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) &&
1400 "Invalid argument in parseArgValues!");
1401 SanitizerMask Kinds;
1402 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1403 const char *Value = A->getValue(i);
1404 SanitizerMask Kind;
1405 // Special case: don't accept -fsanitize=all.
1406 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
1407 0 == strcmp("all", Value))
1408 Kind = SanitizerMask();
1409 else
1410 Kind = parseSanitizerValue(Value, /*AllowGroups=*/true);
1411
1412 if (Kind)
1413 Kinds |= Kind;
1414 else if (DiagnoseErrors)
1415 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1416 << A->getSpelling() << Value;
1417 }
1418 return Kinds;
1419}
1420
1421int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A,
1422 bool DiagnoseErrors) {
1423 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
1424 A->getOption().matches(options::OPT_fno_sanitize_coverage));
1425 int Features = 0;
1426 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1427 const char *Value = A->getValue(i);
1428 int F = llvm::StringSwitch<int>(Value)
1429 .Case("func", CoverageFunc)
1430 .Case("bb", CoverageBB)
1431 .Case("edge", CoverageEdge)
1432 .Case("indirect-calls", CoverageIndirCall)
1433 .Case("trace-bb", CoverageTraceBB)
1434 .Case("trace-cmp", CoverageTraceCmp)
1435 .Case("trace-div", CoverageTraceDiv)
1436 .Case("trace-gep", CoverageTraceGep)
1437 .Case("8bit-counters", Coverage8bitCounters)
1438 .Case("trace-pc", CoverageTracePC)
1439 .Case("trace-pc-guard", CoverageTracePCGuard)
1440 .Case("no-prune", CoverageNoPrune)
1441 .Case("inline-8bit-counters", CoverageInline8bitCounters)
1442 .Case("inline-bool-flag", CoverageInlineBoolFlag)
1443 .Case("pc-table", CoveragePCTable)
1444 .Case("stack-depth", CoverageStackDepth)
1445 .Case("trace-loads", CoverageTraceLoads)
1446 .Case("trace-stores", CoverageTraceStores)
1447 .Case("control-flow", CoverageControlFlow)
1448 .Default(0);
1449 if (F == 0 && DiagnoseErrors)
1450 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1451 << A->getSpelling() << Value;
1452 Features |= F;
1453 }
1454 return Features;
1455}
1456
1457int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A,
1458 bool DiagnoseErrors) {
1459 assert(
1460 A->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ) ||
1461 A->getOption().matches(
1462 options::OPT_fno_experimental_sanitize_metadata_EQ));
1463 int Features = 0;
1464 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1465 const char *Value = A->getValue(i);
1466 int F = llvm::StringSwitch<int>(Value)
1467 .Case("covered", BinaryMetadataCovered)
1468 .Case("atomics", BinaryMetadataAtomics)
1469 .Case("uar", BinaryMetadataUAR)
1470 .Case("all", ~0)
1471 .Default(0);
1472 if (F == 0 && DiagnoseErrors)
1473 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1474 << A->getSpelling() << Value;
1475 Features |= F;
1476 }
1477 return Features;
1478}
1479
1480std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,
1481 SanitizerMask Mask) {
1482 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
1483 E = Args.rend();
1484 I != E; ++I) {
1485 const auto *Arg = *I;
1486 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
1487 SanitizerMask AddKinds =
1488 expandSanitizerGroups(parseArgValues(D, Arg, false));
1489 if (AddKinds & Mask)
1490 return describeSanitizeArg(Arg, Mask);
1491 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
1492 SanitizerMask RemoveKinds =
1493 expandSanitizerGroups(parseArgValues(D, Arg, false));
1494 Mask &= ~RemoveKinds;
1495 }
1496 }
1497 llvm_unreachable("arg list didn't provide expected value");
1498}
1499
1500std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask) {
1501 assert(A->getOption().matches(options::OPT_fsanitize_EQ) &&
1502 "Invalid argument in describeSanitizerArg!");
1503
1504 std::string Sanitizers;
1505 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1507 parseSanitizerValue(A->getValue(i), /*AllowGroups=*/true)) &
1508 Mask) {
1509 if (!Sanitizers.empty())
1510 Sanitizers += ",";
1511 Sanitizers += A->getValue(i);
1512 }
1513 }
1514
1515 assert(!Sanitizers.empty() && "arg didn't provide expected value");
1516 return "-fsanitize=" + Sanitizers;
1517}
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