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