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