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