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) << /*hasReplacement=*/true
801 << "-fsanitize-coverage=trace-pc-guard";
802 }
803 continue;
804 }
805 CoverageFeatures |= parseCoverageFeatures(D, Arg, DiagnoseErrors);
806
807 // Disable coverage and not claim the flags if there is at least one
808 // non-supporting sanitizer.
809 if (!(AllAddedKinds & ~AllRemove & ~setGroupBits(SupportsCoverage))) {
810 Arg->claim();
811 } else {
812 CoverageFeatures = 0;
813 }
814 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
815 Arg->claim();
816 CoverageFeatures &= ~parseCoverageFeatures(D, Arg, DiagnoseErrors);
817 }
818 }
819 // Choose at most one coverage type: function, bb, or edge.
820 if (DiagnoseErrors) {
821 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageBB))
822 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
823 << "-fsanitize-coverage=func"
824 << "-fsanitize-coverage=bb";
825 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageEdge))
826 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
827 << "-fsanitize-coverage=func"
828 << "-fsanitize-coverage=edge";
829 if ((CoverageFeatures & CoverageBB) && (CoverageFeatures & CoverageEdge))
830 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
831 << "-fsanitize-coverage=bb"
832 << "-fsanitize-coverage=edge";
833 // Basic block tracing and 8-bit counters require some type of coverage
834 // enabled.
835 if (CoverageFeatures & CoverageTraceBB)
836 D.Diag(clang::diag::warn_drv_deprecated_arg)
837 << "-fsanitize-coverage=trace-bb" << /*hasReplacement=*/true
838 << "-fsanitize-coverage=trace-pc-guard";
839 if (CoverageFeatures & Coverage8bitCounters)
840 D.Diag(clang::diag::warn_drv_deprecated_arg)
841 << "-fsanitize-coverage=8bit-counters" << /*hasReplacement=*/true
842 << "-fsanitize-coverage=trace-pc-guard";
843 }
844
845 int InsertionPointTypes = CoverageFunc | CoverageBB | CoverageEdge;
846 int InstrumentationTypes = CoverageTracePC | CoverageTracePCGuard |
850 if ((CoverageFeatures & InsertionPointTypes) &&
851 !(CoverageFeatures & InstrumentationTypes) && DiagnoseErrors) {
852 D.Diag(clang::diag::warn_drv_deprecated_arg)
853 << "-fsanitize-coverage=[func|bb|edge]" << /*hasReplacement=*/true
854 << "-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc],["
855 "control-flow]";
856 }
857
858 // trace-pc w/o func/bb/edge implies edge.
859 if (!(CoverageFeatures & InsertionPointTypes)) {
860 if (CoverageFeatures &
863 CoverageFeatures |= CoverageEdge;
864
865 if (CoverageFeatures & CoverageStackDepth)
866 CoverageFeatures |= CoverageFunc;
867 }
868
869 // Parse -fsanitize-coverage-(allow|ignore)list options if coverage enabled.
870 // This also validates special case lists format.
871 // Here, OptSpecifier() acts as a never-matching command-line argument.
872 // So, there is no way to clear coverage lists but you can append to them.
873 if (CoverageFeatures) {
875 D, Args, CoverageAllowlistFiles,
876 options::OPT_fsanitize_coverage_allowlist, OptSpecifier(),
877 clang::diag::err_drv_malformed_sanitizer_coverage_allowlist,
878 DiagnoseErrors);
880 D, Args, CoverageIgnorelistFiles,
881 options::OPT_fsanitize_coverage_ignorelist, OptSpecifier(),
882 clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist,
883 DiagnoseErrors);
884 }
885
886 // Parse -f(no-)?sanitize-metadata.
887 for (const auto *Arg :
888 Args.filtered(options::OPT_fexperimental_sanitize_metadata_EQ,
889 options::OPT_fno_experimental_sanitize_metadata_EQ)) {
890 if (Arg->getOption().matches(
891 options::OPT_fexperimental_sanitize_metadata_EQ)) {
892 Arg->claim();
893 BinaryMetadataFeatures |=
894 parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);
895 } else {
896 Arg->claim();
897 BinaryMetadataFeatures &=
898 ~parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);
899 }
900 }
901
902 // Parse -fsanitize-metadata-ignorelist option if enabled.
903 if (BinaryMetadataFeatures) {
905 D, Args, BinaryMetadataIgnorelistFiles,
906 options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ,
907 OptSpecifier(), // Cannot clear ignore list, only append.
908 clang::diag::err_drv_malformed_sanitizer_metadata_ignorelist,
909 DiagnoseErrors);
910 }
911
912 SharedRuntime =
913 Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan,
914 TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() ||
915 TC.getTriple().isOSDarwin());
916
917 ImplicitCfiRuntime = TC.getTriple().isAndroid();
918
919 if (AllAddedKinds & SanitizerKind::Address) {
920 NeedPIE |= TC.getTriple().isOSFuchsia();
921 if (Arg *A =
922 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
923 StringRef S = A->getValue();
924 // Legal values are 0 and 1, 2, but in future we may add more levels.
925 if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
926 AsanFieldPadding > 2) &&
927 DiagnoseErrors) {
928 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
929 }
930 }
931
932 if (Arg *WindowsDebugRTArg =
933 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
934 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
935 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
936 switch (WindowsDebugRTArg->getOption().getID()) {
937 case options::OPT__SLASH_MTd:
938 case options::OPT__SLASH_MDd:
939 case options::OPT__SLASH_LDd:
940 if (DiagnoseErrors) {
941 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
942 << WindowsDebugRTArg->getAsString(Args)
943 << lastArgumentForMask(D, Args, SanitizerKind::Address);
944 D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
945 }
946 }
947 }
948
949 StableABI = Args.hasFlag(options::OPT_fsanitize_stable_abi,
950 options::OPT_fno_sanitize_stable_abi, false);
951
952 AsanUseAfterScope = Args.hasFlag(
953 options::OPT_fsanitize_address_use_after_scope,
954 options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);
955
956 AsanPoisonCustomArrayCookie = Args.hasFlag(
957 options::OPT_fsanitize_address_poison_custom_array_cookie,
958 options::OPT_fno_sanitize_address_poison_custom_array_cookie,
959 AsanPoisonCustomArrayCookie);
960
961 AsanOutlineInstrumentation =
962 Args.hasFlag(options::OPT_fsanitize_address_outline_instrumentation,
963 options::OPT_fno_sanitize_address_outline_instrumentation,
964 AsanOutlineInstrumentation);
965
966 AsanGlobalsDeadStripping = Args.hasFlag(
967 options::OPT_fsanitize_address_globals_dead_stripping,
968 options::OPT_fno_sanitize_address_globals_dead_stripping, true);
969
970 // Enable ODR indicators which allow better handling of mixed instrumented
971 // and uninstrumented globals. Disable them for Windows where weak odr
972 // indicators (.weak.__odr_asan_gen*) may cause multiple definition linker
973 // errors in the absence of -lldmingw.
974 AsanUseOdrIndicator =
975 Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
976 options::OPT_fno_sanitize_address_use_odr_indicator,
977 !TC.getTriple().isOSWindows());
978
979 if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) {
980 AsanInvalidPointerCmp = true;
981 }
982
983 if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) {
984 AsanInvalidPointerSub = true;
985 }
986
987 if (TC.getTriple().isOSDarwin() &&
988 (Args.hasArg(options::OPT_mkernel) ||
989 Args.hasArg(options::OPT_fapple_kext))) {
990 AsanDtorKind = llvm::AsanDtorKind::None;
991 }
992
993 if (const auto *Arg =
994 Args.getLastArg(options::OPT_sanitize_address_destructor_EQ)) {
995 auto parsedAsanDtorKind = AsanDtorKindFromString(Arg->getValue());
996 if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid && DiagnoseErrors) {
997 TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)
998 << Arg->getSpelling() << Arg->getValue();
999 }
1000 AsanDtorKind = parsedAsanDtorKind;
1001 }
1002
1003 if (const auto *Arg = Args.getLastArg(
1004 options::OPT_sanitize_address_use_after_return_EQ)) {
1005 auto parsedAsanUseAfterReturn =
1007 if (parsedAsanUseAfterReturn ==
1008 llvm::AsanDetectStackUseAfterReturnMode::Invalid &&
1009 DiagnoseErrors) {
1010 TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)
1011 << Arg->getSpelling() << Arg->getValue();
1012 }
1013 AsanUseAfterReturn = parsedAsanUseAfterReturn;
1014 }
1015
1016 } else {
1017 AsanUseAfterScope = false;
1018 // -fsanitize=pointer-compare/pointer-subtract requires -fsanitize=address.
1019 SanitizerMask DetectInvalidPointerPairs =
1020 SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract;
1021 if ((AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) &&
1022 DiagnoseErrors) {
1023 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)
1024 << lastArgumentForMask(D, Args,
1025 SanitizerKind::PointerCompare |
1026 SanitizerKind::PointerSubtract)
1027 << "-fsanitize=address";
1028 }
1029 }
1030
1031 if (AllAddedKinds & SanitizerKind::HWAddress) {
1032 if (Arg *HwasanAbiArg =
1033 Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {
1034 HwasanAbi = HwasanAbiArg->getValue();
1035 if (HwasanAbi != "platform" && HwasanAbi != "interceptor" &&
1036 DiagnoseErrors)
1037 D.Diag(clang::diag::err_drv_invalid_value)
1038 << HwasanAbiArg->getAsString(Args) << HwasanAbi;
1039 } else {
1040 HwasanAbi = "interceptor";
1041 }
1042 if (TC.getTriple().getArch() == llvm::Triple::x86_64)
1043 HwasanUseAliases = Args.hasFlag(
1044 options::OPT_fsanitize_hwaddress_experimental_aliasing,
1045 options::OPT_fno_sanitize_hwaddress_experimental_aliasing,
1046 HwasanUseAliases);
1047 }
1048
1049 if (AllAddedKinds & SanitizerKind::SafeStack) {
1050 // SafeStack runtime is built into the system on Android and Fuchsia.
1051 SafeStackRuntime =
1052 !TC.getTriple().isAndroid() && !TC.getTriple().isOSFuchsia();
1053 }
1054
1055 LinkRuntimes =
1056 Args.hasFlag(options::OPT_fsanitize_link_runtime,
1057 options::OPT_fno_sanitize_link_runtime, LinkRuntimes);
1058
1059 // Parse -link-cxx-sanitizer flag.
1060 LinkCXXRuntimes = Args.hasArg(options::OPT_fsanitize_link_cxx_runtime,
1061 options::OPT_fno_sanitize_link_cxx_runtime,
1062 LinkCXXRuntimes) ||
1063 D.CCCIsCXX();
1064
1065 NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile,
1066 options::OPT_fmemory_profile_EQ,
1067 options::OPT_fno_memory_profile, false);
1068
1069 // Finally, initialize the set of available and recoverable sanitizers.
1070 Sanitizers.Mask |= Kinds;
1071 RecoverableSanitizers.Mask |= RecoverableKinds;
1072 TrapSanitizers.Mask |= TrappingKinds;
1073 assert(!(RecoverableKinds & TrappingKinds) &&
1074 "Overlap between recoverable and trapping sanitizers");
1075}
1076
1077static std::string toString(const clang::SanitizerSet &Sanitizers) {
1078 std::string Res;
1079#define SANITIZER(NAME, ID) \
1080 if (Sanitizers.has(SanitizerKind::ID)) { \
1081 if (!Res.empty()) \
1082 Res += ","; \
1083 Res += NAME; \
1084 }
1085#include "clang/Basic/Sanitizers.def"
1086 return Res;
1087}
1088
1089static void addSpecialCaseListOpt(const llvm::opt::ArgList &Args,
1090 llvm::opt::ArgStringList &CmdArgs,
1091 const char *SCLOptFlag,
1092 const std::vector<std::string> &SCLFiles) {
1093 for (const auto &SCLPath : SCLFiles) {
1094 SmallString<64> SCLOpt(SCLOptFlag);
1095 SCLOpt += SCLPath;
1096 CmdArgs.push_back(Args.MakeArgString(SCLOpt));
1097 }
1098}
1099
1100static void addIncludeLinkerOption(const ToolChain &TC,
1101 const llvm::opt::ArgList &Args,
1102 llvm::opt::ArgStringList &CmdArgs,
1103 StringRef SymbolName) {
1104 SmallString<64> LinkerOptionFlag;
1105 LinkerOptionFlag = "--linker-option=/include:";
1106 if (TC.getTriple().getArch() == llvm::Triple::x86) {
1107 // Win32 mangles C function names with a '_' prefix.
1108 LinkerOptionFlag += '_';
1109 }
1110 LinkerOptionFlag += SymbolName;
1111 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
1112}
1113
1114static bool hasTargetFeatureMTE(const llvm::opt::ArgStringList &CmdArgs) {
1115 for (auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End;
1116 ++Start) {
1117 auto It = std::find(Start, End, StringRef("+mte"));
1118 if (It == End)
1119 break;
1120 if (It > Start && *std::prev(It) == StringRef("-target-feature"))
1121 return true;
1122 Start = It;
1123 }
1124 return false;
1125}
1126
1127void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
1128 llvm::opt::ArgStringList &CmdArgs,
1129 types::ID InputType) const {
1130 // NVPTX doesn't currently support sanitizers. Bailing out here means
1131 // that e.g. -fsanitize=address applies only to host code, which is what we
1132 // want for now.
1133 if (TC.getTriple().isNVPTX())
1134 return;
1135 // AMDGPU sanitizer support is experimental and controlled by -fgpu-sanitize.
1136 bool GPUSanitize = false;
1137 if (TC.getTriple().isAMDGPU()) {
1138 if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
1139 true))
1140 return;
1141 GPUSanitize = true;
1142 }
1143
1144 // Translate available CoverageFeatures to corresponding clang-cc1 flags.
1145 // Do it even if Sanitizers.empty() since some forms of coverage don't require
1146 // sanitizers.
1147 std::pair<int, const char *> CoverageFlags[] = {
1148 std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"),
1149 std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"),
1150 std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"),
1151 std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"),
1152 std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"),
1153 std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"),
1154 std::make_pair(CoverageTraceDiv, "-fsanitize-coverage-trace-div"),
1155 std::make_pair(CoverageTraceGep, "-fsanitize-coverage-trace-gep"),
1156 std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"),
1157 std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"),
1158 std::make_pair(CoverageTracePCGuard,
1159 "-fsanitize-coverage-trace-pc-guard"),
1160 std::make_pair(CoverageInline8bitCounters,
1161 "-fsanitize-coverage-inline-8bit-counters"),
1162 std::make_pair(CoverageInlineBoolFlag,
1163 "-fsanitize-coverage-inline-bool-flag"),
1164 std::make_pair(CoveragePCTable, "-fsanitize-coverage-pc-table"),
1165 std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune"),
1166 std::make_pair(CoverageStackDepth, "-fsanitize-coverage-stack-depth"),
1167 std::make_pair(CoverageTraceLoads, "-fsanitize-coverage-trace-loads"),
1168 std::make_pair(CoverageTraceStores, "-fsanitize-coverage-trace-stores"),
1169 std::make_pair(CoverageControlFlow, "-fsanitize-coverage-control-flow")};
1170 for (auto F : CoverageFlags) {
1171 if (CoverageFeatures & F.first)
1172 CmdArgs.push_back(F.second);
1173 }
1175 Args, CmdArgs, "-fsanitize-coverage-allowlist=", CoverageAllowlistFiles);
1176 addSpecialCaseListOpt(Args, CmdArgs, "-fsanitize-coverage-ignorelist=",
1177 CoverageIgnorelistFiles);
1178
1179 if (!GPUSanitize) {
1180 // Translate available BinaryMetadataFeatures to corresponding clang-cc1
1181 // flags. Does not depend on any other sanitizers. Unsupported on GPUs.
1182 const std::pair<int, std::string> BinaryMetadataFlags[] = {
1183 std::make_pair(BinaryMetadataCovered, "covered"),
1184 std::make_pair(BinaryMetadataAtomics, "atomics"),
1185 std::make_pair(BinaryMetadataUAR, "uar")};
1186 for (const auto &F : BinaryMetadataFlags) {
1187 if (BinaryMetadataFeatures & F.first)
1188 CmdArgs.push_back(
1189 Args.MakeArgString("-fexperimental-sanitize-metadata=" + F.second));
1190 }
1191 addSpecialCaseListOpt(Args, CmdArgs,
1192 "-fexperimental-sanitize-metadata-ignorelist=",
1193 BinaryMetadataIgnorelistFiles);
1194 }
1195
1196 if (TC.getTriple().isOSWindows() && needsUbsanRt() &&
1197 Args.hasFlag(options::OPT_frtlib_defaultlib,
1198 options::OPT_fno_rtlib_defaultlib, true)) {
1199 // Instruct the code generator to embed linker directives in the object file
1200 // that cause the required runtime libraries to be linked.
1201 CmdArgs.push_back(
1202 Args.MakeArgString("--dependent-lib=" +
1203 TC.getCompilerRTBasename(Args, "ubsan_standalone")));
1204 if (types::isCXX(InputType))
1205 CmdArgs.push_back(Args.MakeArgString(
1206 "--dependent-lib=" +
1207 TC.getCompilerRTBasename(Args, "ubsan_standalone_cxx")));
1208 }
1209 if (TC.getTriple().isOSWindows() && needsStatsRt() &&
1210 Args.hasFlag(options::OPT_frtlib_defaultlib,
1211 options::OPT_fno_rtlib_defaultlib, true)) {
1212 CmdArgs.push_back(Args.MakeArgString(
1213 "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats_client")));
1214
1215 // The main executable must export the stats runtime.
1216 // FIXME: Only exporting from the main executable (e.g. based on whether the
1217 // translation unit defines main()) would save a little space, but having
1218 // multiple copies of the runtime shouldn't hurt.
1219 CmdArgs.push_back(Args.MakeArgString(
1220 "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats")));
1221 addIncludeLinkerOption(TC, Args, CmdArgs, "__sanitizer_stats_register");
1222 }
1223
1224 if (Sanitizers.empty())
1225 return;
1226 CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers)));
1227
1228 if (!RecoverableSanitizers.empty())
1229 CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" +
1230 toString(RecoverableSanitizers)));
1231
1232 if (!TrapSanitizers.empty())
1233 CmdArgs.push_back(
1234 Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));
1235
1236 addSpecialCaseListOpt(Args, CmdArgs,
1237 "-fsanitize-ignorelist=", UserIgnorelistFiles);
1238 addSpecialCaseListOpt(Args, CmdArgs,
1239 "-fsanitize-system-ignorelist=", SystemIgnorelistFiles);
1240
1241 if (MsanTrackOrigins)
1242 CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" +
1243 Twine(MsanTrackOrigins)));
1244
1245 if (MsanUseAfterDtor)
1246 CmdArgs.push_back("-fsanitize-memory-use-after-dtor");
1247
1248 if (!MsanParamRetval)
1249 CmdArgs.push_back("-fno-sanitize-memory-param-retval");
1250
1251 // FIXME: Pass these parameters as function attributes, not as -llvm flags.
1252 if (!TsanMemoryAccess) {
1253 CmdArgs.push_back("-mllvm");
1254 CmdArgs.push_back("-tsan-instrument-memory-accesses=0");
1255 CmdArgs.push_back("-mllvm");
1256 CmdArgs.push_back("-tsan-instrument-memintrinsics=0");
1257 }
1258 if (!TsanFuncEntryExit) {
1259 CmdArgs.push_back("-mllvm");
1260 CmdArgs.push_back("-tsan-instrument-func-entry-exit=0");
1261 }
1262 if (!TsanAtomics) {
1263 CmdArgs.push_back("-mllvm");
1264 CmdArgs.push_back("-tsan-instrument-atomics=0");
1265 }
1266
1267 if (HwasanUseAliases) {
1268 CmdArgs.push_back("-mllvm");
1269 CmdArgs.push_back("-hwasan-experimental-use-page-aliases=1");
1270 }
1271
1272 if (CfiCrossDso)
1273 CmdArgs.push_back("-fsanitize-cfi-cross-dso");
1274
1275 if (CfiICallGeneralizePointers)
1276 CmdArgs.push_back("-fsanitize-cfi-icall-generalize-pointers");
1277
1278 if (CfiICallNormalizeIntegers)
1279 CmdArgs.push_back("-fsanitize-cfi-icall-experimental-normalize-integers");
1280
1281 if (CfiCanonicalJumpTables)
1282 CmdArgs.push_back("-fsanitize-cfi-canonical-jump-tables");
1283
1284 if (Stats)
1285 CmdArgs.push_back("-fsanitize-stats");
1286
1287 if (MinimalRuntime)
1288 CmdArgs.push_back("-fsanitize-minimal-runtime");
1289
1290 if (AsanFieldPadding)
1291 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" +
1292 Twine(AsanFieldPadding)));
1293
1294 if (AsanUseAfterScope)
1295 CmdArgs.push_back("-fsanitize-address-use-after-scope");
1296
1297 if (AsanPoisonCustomArrayCookie)
1298 CmdArgs.push_back("-fsanitize-address-poison-custom-array-cookie");
1299
1300 if (AsanGlobalsDeadStripping)
1301 CmdArgs.push_back("-fsanitize-address-globals-dead-stripping");
1302
1303 if (!AsanUseOdrIndicator)
1304 CmdArgs.push_back("-fno-sanitize-address-use-odr-indicator");
1305
1306 if (AsanInvalidPointerCmp) {
1307 CmdArgs.push_back("-mllvm");
1308 CmdArgs.push_back("-asan-detect-invalid-pointer-cmp");
1309 }
1310
1311 if (AsanInvalidPointerSub) {
1312 CmdArgs.push_back("-mllvm");
1313 CmdArgs.push_back("-asan-detect-invalid-pointer-sub");
1314 }
1315
1316 if (AsanOutlineInstrumentation) {
1317 CmdArgs.push_back("-mllvm");
1318 CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");
1319 }
1320
1321 // When emitting Stable ABI instrumentation, force outlining calls and avoid
1322 // inlining shadow memory poisoning. While this is a big performance burden
1323 // for now it allows full abstraction from implementation details.
1324 if (StableABI) {
1325 CmdArgs.push_back("-mllvm");
1326 CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");
1327 CmdArgs.push_back("-mllvm");
1328 CmdArgs.push_back("-asan-max-inline-poisoning-size=0");
1329 CmdArgs.push_back("-mllvm");
1330 CmdArgs.push_back("-asan-guard-against-version-mismatch=0");
1331 }
1332
1333 // Only pass the option to the frontend if the user requested,
1334 // otherwise the frontend will just use the codegen default.
1335 if (AsanDtorKind != llvm::AsanDtorKind::Invalid) {
1336 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-destructor=" +
1337 AsanDtorKindToString(AsanDtorKind)));
1338 }
1339
1340 if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
1341 CmdArgs.push_back(Args.MakeArgString(
1342 "-fsanitize-address-use-after-return=" +
1343 AsanDetectStackUseAfterReturnModeToString(AsanUseAfterReturn)));
1344 }
1345
1346 if (!HwasanAbi.empty()) {
1347 CmdArgs.push_back("-default-function-attr");
1348 CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi));
1349 }
1350
1351 if (Sanitizers.has(SanitizerKind::HWAddress) && !HwasanUseAliases) {
1352 CmdArgs.push_back("-target-feature");
1353 CmdArgs.push_back("+tagged-globals");
1354 }
1355
1356 // MSan: Workaround for PR16386.
1357 // ASan: This is mainly to help LSan with cases such as
1358 // https://github.com/google/sanitizers/issues/373
1359 // We can't make this conditional on -fsanitize=leak, as that flag shouldn't
1360 // affect compilation.
1361 if (Sanitizers.has(SanitizerKind::Memory) ||
1362 Sanitizers.has(SanitizerKind::Address))
1363 CmdArgs.push_back("-fno-assume-sane-operator-new");
1364
1365 // libFuzzer wants to intercept calls to certain library functions, so the
1366 // following -fno-builtin-* flags force the compiler to emit interposable
1367 // libcalls to these functions. Other sanitizers effectively do the same thing
1368 // by marking all library call sites with NoBuiltin attribute in their LLVM
1369 // pass. (see llvm::maybeMarkSanitizerLibraryCallNoBuiltin)
1370 if (Sanitizers.has(SanitizerKind::FuzzerNoLink)) {
1371 CmdArgs.push_back("-fno-builtin-bcmp");
1372 CmdArgs.push_back("-fno-builtin-memcmp");
1373 CmdArgs.push_back("-fno-builtin-strncmp");
1374 CmdArgs.push_back("-fno-builtin-strcmp");
1375 CmdArgs.push_back("-fno-builtin-strncasecmp");
1376 CmdArgs.push_back("-fno-builtin-strcasecmp");
1377 CmdArgs.push_back("-fno-builtin-strstr");
1378 CmdArgs.push_back("-fno-builtin-strcasestr");
1379 CmdArgs.push_back("-fno-builtin-memmem");
1380 }
1381
1382 // Require -fvisibility= flag on non-Windows when compiling if vptr CFI is
1383 // enabled.
1384 if (Sanitizers.hasOneOf(CFIClasses) && !TC.getTriple().isOSWindows() &&
1385 !Args.hasArg(options::OPT_fvisibility_EQ)) {
1386 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)
1387 << lastArgumentForMask(TC.getDriver(), Args,
1388 Sanitizers.Mask & CFIClasses)
1389 << "-fvisibility=";
1390 }
1391
1392 if (Sanitizers.has(SanitizerKind::MemtagStack) &&
1393 !hasTargetFeatureMTE(CmdArgs))
1394 TC.getDriver().Diag(diag::err_stack_tagging_requires_hardware_feature);
1395}
1396
1397SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
1398 bool DiagnoseErrors) {
1399 assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
1400 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
1401 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
1402 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
1403 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
1404 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) &&
1405 "Invalid argument in parseArgValues!");
1406 SanitizerMask Kinds;
1407 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1408 const char *Value = A->getValue(i);
1409 SanitizerMask Kind;
1410 // Special case: don't accept -fsanitize=all.
1411 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
1412 0 == strcmp("all", Value))
1413 Kind = SanitizerMask();
1414 else
1415 Kind = parseSanitizerValue(Value, /*AllowGroups=*/true);
1416
1417 if (Kind)
1418 Kinds |= Kind;
1419 else if (DiagnoseErrors)
1420 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1421 << A->getSpelling() << Value;
1422 }
1423 return Kinds;
1424}
1425
1426int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A,
1427 bool DiagnoseErrors) {
1428 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
1429 A->getOption().matches(options::OPT_fno_sanitize_coverage));
1430 int Features = 0;
1431 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1432 const char *Value = A->getValue(i);
1433 int F = llvm::StringSwitch<int>(Value)
1434 .Case("func", CoverageFunc)
1435 .Case("bb", CoverageBB)
1436 .Case("edge", CoverageEdge)
1437 .Case("indirect-calls", CoverageIndirCall)
1438 .Case("trace-bb", CoverageTraceBB)
1439 .Case("trace-cmp", CoverageTraceCmp)
1440 .Case("trace-div", CoverageTraceDiv)
1441 .Case("trace-gep", CoverageTraceGep)
1442 .Case("8bit-counters", Coverage8bitCounters)
1443 .Case("trace-pc", CoverageTracePC)
1444 .Case("trace-pc-guard", CoverageTracePCGuard)
1445 .Case("no-prune", CoverageNoPrune)
1446 .Case("inline-8bit-counters", CoverageInline8bitCounters)
1447 .Case("inline-bool-flag", CoverageInlineBoolFlag)
1448 .Case("pc-table", CoveragePCTable)
1449 .Case("stack-depth", CoverageStackDepth)
1450 .Case("trace-loads", CoverageTraceLoads)
1451 .Case("trace-stores", CoverageTraceStores)
1452 .Case("control-flow", CoverageControlFlow)
1453 .Default(0);
1454 if (F == 0 && DiagnoseErrors)
1455 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1456 << A->getSpelling() << Value;
1457 Features |= F;
1458 }
1459 return Features;
1460}
1461
1462int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A,
1463 bool DiagnoseErrors) {
1464 assert(
1465 A->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ) ||
1466 A->getOption().matches(
1467 options::OPT_fno_experimental_sanitize_metadata_EQ));
1468 int Features = 0;
1469 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1470 const char *Value = A->getValue(i);
1471 int F = llvm::StringSwitch<int>(Value)
1472 .Case("covered", BinaryMetadataCovered)
1473 .Case("atomics", BinaryMetadataAtomics)
1474 .Case("uar", BinaryMetadataUAR)
1475 .Case("all", ~0)
1476 .Default(0);
1477 if (F == 0 && DiagnoseErrors)
1478 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1479 << A->getSpelling() << Value;
1480 Features |= F;
1481 }
1482 return Features;
1483}
1484
1485std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,
1486 SanitizerMask Mask) {
1487 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
1488 E = Args.rend();
1489 I != E; ++I) {
1490 const auto *Arg = *I;
1491 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
1492 SanitizerMask AddKinds =
1493 expandSanitizerGroups(parseArgValues(D, Arg, false));
1494 if (AddKinds & Mask)
1495 return describeSanitizeArg(Arg, Mask);
1496 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
1497 SanitizerMask RemoveKinds =
1498 expandSanitizerGroups(parseArgValues(D, Arg, false));
1499 Mask &= ~RemoveKinds;
1500 }
1501 }
1502 llvm_unreachable("arg list didn't provide expected value");
1503}
1504
1505std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask) {
1506 assert(A->getOption().matches(options::OPT_fsanitize_EQ) &&
1507 "Invalid argument in describeSanitizerArg!");
1508
1509 std::string Sanitizers;
1510 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1512 parseSanitizerValue(A->getValue(i), /*AllowGroups=*/true)) &
1513 Mask) {
1514 if (!Sanitizers.empty())
1515 Sanitizers += ",";
1516 Sanitizers += A->getValue(i);
1517 }
1518 }
1519
1520 assert(!Sanitizers.empty() && "arg didn't provide expected value");
1521 return "-fsanitize=" + Sanitizers;
1522}
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:717
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:1360
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