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