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 std::make_pair(SanitizerKind::AllocToken,
673 SanitizerKind::Address | SanitizerKind::HWAddress |
674 SanitizerKind::KernelAddress |
675 SanitizerKind::KernelHWAddress |
676 SanitizerKind::Memory)};
677
678 // Enable toolchain specific default sanitizers if not explicitly disabled.
679 SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove;
680
681 // Disable default sanitizers that are incompatible with explicitly requested
682 // ones.
683 for (auto G : IncompatibleGroups) {
684 SanitizerMask Group = G.first;
685 if ((Default & Group) && (Kinds & G.second))
686 Default &= ~Group;
687 }
688
689 Kinds |= Default;
690
691 // We disable the vptr sanitizer if it was enabled by group expansion but RTTI
692 // is disabled.
693 if ((Kinds & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {
694 Kinds &= ~SanitizerKind::Vptr;
695 }
696
697 // Check that LTO is enabled if we need it.
698 if ((Kinds & NeedsLTO) && !D.isUsingLTO() && DiagnoseErrors) {
699 D.Diag(diag::err_drv_argument_only_allowed_with)
700 << lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto";
701 }
702
703 if ((Kinds & SanitizerKind::ShadowCallStack) && TC.getTriple().isAArch64() &&
704 !llvm::AArch64::isX18ReservedByDefault(TC.getTriple()) &&
705 !Args.hasArg(options::OPT_ffixed_x18) && DiagnoseErrors) {
706 D.Diag(diag::err_drv_argument_only_allowed_with)
707 << lastArgumentForMask(D, Args, Kinds & SanitizerKind::ShadowCallStack)
708 << "-ffixed-x18";
709 }
710
711 // Report error if there are non-trapping sanitizers that require
712 // c++abi-specific parts of UBSan runtime, and they are not provided by the
713 // toolchain. We don't have a good way to check the latter, so we just
714 // check if the toolchan supports vptr.
715 if (~Supported & SanitizerKind::Vptr) {
716 SanitizerMask KindsToDiagnose = Kinds & ~TrappingKinds & NeedsUbsanCxxRt;
717 // The runtime library supports the Microsoft C++ ABI, but only well enough
718 // for CFI. FIXME: Remove this once we support vptr on Windows.
719 if (TC.getTriple().isOSWindows())
720 KindsToDiagnose &= ~SanitizerKind::CFI;
721 if (KindsToDiagnose) {
722 SanitizerSet S;
723 S.Mask = KindsToDiagnose;
724 if (DiagnoseErrors)
725 D.Diag(diag::err_drv_unsupported_opt_for_target)
726 << ("-fno-sanitize-trap=" + toString(S)) << TC.getTriple().str();
727 Kinds &= ~KindsToDiagnose;
728 }
729 }
730
731 // Warn about incompatible groups of sanitizers.
732 for (auto G : IncompatibleGroups) {
733 SanitizerMask Group = G.first;
734 if (Kinds & Group) {
735 if (SanitizerMask Incompatible = Kinds & G.second) {
736 if (DiagnoseErrors)
737 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
738 << lastArgumentForMask(D, Args, Group)
740 Kinds &= ~Incompatible;
741 }
742 }
743 }
744 // FIXME: Currently -fsanitize=leak is silently ignored in the presence of
745 // -fsanitize=address. Perhaps it should print an error, or perhaps
746 // -f(-no)sanitize=leak should change whether leak detection is enabled by
747 // default in ASan?
748
749 // Parse -f(no-)?sanitize-recover flags.
750 SanitizerMask RecoverableKinds = parseSanitizeArgs(
751 D, Args, DiagnoseErrors, RecoverableByDefault, AlwaysRecoverable,
752 Unrecoverable, options::OPT_fsanitize_recover_EQ,
753 options::OPT_fno_sanitize_recover_EQ);
754 RecoverableKinds &= Kinds;
755
756 TrappingKinds &= Kinds;
757 RecoverableKinds &= ~TrappingKinds;
758
759 // Parse -f(no-)?sanitize-nonmerged-handlers flags
760 SanitizerMask MergeKinds =
761 parseSanitizeArgs(D, Args, DiagnoseErrors, MergeDefault, {}, {},
762 options::OPT_fsanitize_merge_handlers_EQ,
763 options::OPT_fno_sanitize_merge_handlers_EQ);
764 MergeKinds &= Kinds;
765
766 // Parse -fno-fsanitize-skip-hot-cutoff flags
767 SkipHotCutoffs = parseSanitizeSkipHotCutoffArgs(D, Args, DiagnoseErrors);
768
769 // Parse -f(no-)?sanitize-annotate-debug-info flags
770 SanitizerMask AnnotateDebugInfoKinds =
771 parseSanitizeArgs(D, Args, DiagnoseErrors, AnnotateDebugInfoDefault, {},
772 {}, options::OPT_fsanitize_annotate_debug_info_EQ,
773 options::OPT_fno_sanitize_annotate_debug_info_EQ);
774 AnnotateDebugInfoKinds &= Kinds;
775
776 // Setup ignorelist files.
777 // Add default ignorelist from resource directory for activated sanitizers,
778 // and validate special case lists format.
779 if (!Args.hasArgNoClaim(options::OPT_fno_sanitize_ignorelist))
780 addDefaultIgnorelists(D, Kinds, SystemIgnorelistFiles, DiagnoseErrors);
781
782 // Parse -f(no-)?sanitize-ignorelist options.
783 // This also validates special case lists format.
785 D, Args, UserIgnorelistFiles, options::OPT_fsanitize_ignorelist_EQ,
786 options::OPT_fno_sanitize_ignorelist,
787 clang::diag::err_drv_malformed_sanitizer_ignorelist, DiagnoseErrors);
788
789 // Verify that -fsanitize-coverage-stack-depth-callback-min is >= 0.
790 if (Arg *A = Args.getLastArg(
791 options::OPT_fsanitize_coverage_stack_depth_callback_min_EQ)) {
792 StringRef S = A->getValue();
793 if (S.getAsInteger(0, CoverageStackDepthCallbackMin) ||
794 CoverageStackDepthCallbackMin < 0) {
795 if (DiagnoseErrors)
796 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
797 }
798 }
799
800 // Parse -f[no-]sanitize-memory-track-origins[=level] options.
801 if (AllAddedKinds & SanitizerKind::Memory) {
802 if (Arg *A =
803 Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
804 options::OPT_fno_sanitize_memory_track_origins)) {
805 if (!A->getOption().matches(
806 options::OPT_fno_sanitize_memory_track_origins)) {
807 StringRef S = A->getValue();
808 if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
809 MsanTrackOrigins > 2) {
810 if (DiagnoseErrors)
811 D.Diag(clang::diag::err_drv_invalid_value)
812 << A->getAsString(Args) << S;
813 }
814 }
815 }
816 MsanUseAfterDtor = Args.hasFlag(
817 options::OPT_fsanitize_memory_use_after_dtor,
818 options::OPT_fno_sanitize_memory_use_after_dtor, MsanUseAfterDtor);
819 MsanParamRetval = Args.hasFlag(
820 options::OPT_fsanitize_memory_param_retval,
821 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
822 } else if (AllAddedKinds & SanitizerKind::KernelMemory) {
823 MsanUseAfterDtor = false;
824 MsanParamRetval = Args.hasFlag(
825 options::OPT_fsanitize_memory_param_retval,
826 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
827 } else {
828 MsanUseAfterDtor = false;
829 MsanParamRetval = false;
830 }
831
832 if (AllAddedKinds & SanitizerKind::MemTag) {
833 StringRef S =
834 Args.getLastArgValue(options::OPT_fsanitize_memtag_mode_EQ, "sync");
835 if (S == "async" || S == "sync") {
836 MemtagMode = S.str();
837 } else {
838 D.Diag(clang::diag::err_drv_invalid_value_with_suggestion)
839 << "-fsanitize-memtag-mode=" << S << "{async, sync}";
840 MemtagMode = "sync";
841 }
842 }
843
844 if (AllAddedKinds & SanitizerKind::Thread) {
845 TsanMemoryAccess = Args.hasFlag(
846 options::OPT_fsanitize_thread_memory_access,
847 options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess);
848 TsanFuncEntryExit = Args.hasFlag(
849 options::OPT_fsanitize_thread_func_entry_exit,
850 options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit);
851 TsanAtomics =
852 Args.hasFlag(options::OPT_fsanitize_thread_atomics,
853 options::OPT_fno_sanitize_thread_atomics, TsanAtomics);
854 }
855
856 if (AllAddedKinds & SanitizerKind::CFI) {
857 // Without PIE, external function address may resolve to a PLT record, which
858 // can not be verified by the target module.
859 NeedPIE |= CfiCrossDso;
860 CfiICallGeneralizePointers =
861 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
862
863 CfiICallNormalizeIntegers =
864 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
865
866 if (CfiCrossDso && CfiICallGeneralizePointers && DiagnoseErrors)
867 D.Diag(diag::err_drv_argument_not_allowed_with)
868 << "-fsanitize-cfi-cross-dso"
869 << "-fsanitize-cfi-icall-generalize-pointers";
870
871 CfiCanonicalJumpTables =
872 Args.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables,
873 options::OPT_fno_sanitize_cfi_canonical_jump_tables, true);
874 }
875
876 if (AllAddedKinds & SanitizerKind::KCFI) {
877 CfiICallGeneralizePointers =
878 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
879 CfiICallNormalizeIntegers =
880 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
881
882 KcfiArity = Args.hasArg(options::OPT_fsanitize_kcfi_arity);
883
884 if (AllAddedKinds & SanitizerKind::CFI && DiagnoseErrors)
885 D.Diag(diag::err_drv_argument_not_allowed_with)
886 << "-fsanitize=kcfi"
887 << lastArgumentForMask(D, Args, SanitizerKind::CFI);
888 }
889
890 Stats = Args.hasFlag(options::OPT_fsanitize_stats,
891 options::OPT_fno_sanitize_stats, false);
892
893 if (MinimalRuntime) {
894 SanitizerMask IncompatibleMask =
896 if (IncompatibleMask && DiagnoseErrors)
897 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
898 << "-fsanitize-minimal-runtime"
899 << lastArgumentForMask(D, Args, IncompatibleMask);
900 }
901
902 for (const auto *Arg : Args.filtered(
903 options::OPT_fsanitize_undefined_ignore_overflow_pattern_EQ)) {
904 Arg->claim();
905 OverflowPatternExclusions |=
906 parseOverflowPatternExclusionValues(D, Arg, DiagnoseErrors);
907 }
908
909 // Parse -f(no-)?sanitize-coverage flags if coverage is supported by the
910 // enabled sanitizers.
911 for (const auto *Arg : Args) {
912 if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
913 int LegacySanitizeCoverage;
914 if (Arg->getNumValues() == 1 &&
915 !StringRef(Arg->getValue(0))
916 .getAsInteger(0, LegacySanitizeCoverage)) {
917 CoverageFeatures = 0;
918 Arg->claim();
919 if (LegacySanitizeCoverage != 0 && DiagnoseErrors) {
920 D.Diag(diag::warn_drv_deprecated_arg)
921 << Arg->getAsString(Args) << /*hasReplacement=*/true
922 << "-fsanitize-coverage=trace-pc-guard";
923 }
924 continue;
925 }
926 CoverageFeatures |= parseCoverageFeatures(D, Arg, DiagnoseErrors);
927
928 // Disable coverage and not claim the flags if there is at least one
929 // non-supporting sanitizer.
930 if (!(AllAddedKinds & ~AllRemove & ~setGroupBits(SupportsCoverage))) {
931 Arg->claim();
932 } else {
933 CoverageFeatures = 0;
934 }
935 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
936 Arg->claim();
937 CoverageFeatures &= ~parseCoverageFeatures(D, Arg, DiagnoseErrors);
938 }
939 }
940 // Choose at most one coverage type: function, bb, or edge.
941 if (DiagnoseErrors) {
942 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageBB))
943 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
944 << "-fsanitize-coverage=func"
945 << "-fsanitize-coverage=bb";
946 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageEdge))
947 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
948 << "-fsanitize-coverage=func"
949 << "-fsanitize-coverage=edge";
950 if ((CoverageFeatures & CoverageBB) && (CoverageFeatures & CoverageEdge))
951 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
952 << "-fsanitize-coverage=bb"
953 << "-fsanitize-coverage=edge";
954 // Basic block tracing and 8-bit counters require some type of coverage
955 // enabled.
956 if (CoverageFeatures & CoverageTraceBB)
957 D.Diag(clang::diag::warn_drv_deprecated_arg)
958 << "-fsanitize-coverage=trace-bb" << /*hasReplacement=*/true
959 << "-fsanitize-coverage=trace-pc-guard";
960 if (CoverageFeatures & Coverage8bitCounters)
961 D.Diag(clang::diag::warn_drv_deprecated_arg)
962 << "-fsanitize-coverage=8bit-counters" << /*hasReplacement=*/true
963 << "-fsanitize-coverage=trace-pc-guard";
964 }
965
966 int InsertionPointTypes = CoverageFunc | CoverageBB | CoverageEdge;
967 int InstrumentationTypes = CoverageTracePC | CoverageTracePCEntryExit |
971 if ((CoverageFeatures & InsertionPointTypes) &&
972 !(CoverageFeatures & InstrumentationTypes) && DiagnoseErrors) {
973 D.Diag(clang::diag::warn_drv_deprecated_arg)
974 << "-fsanitize-coverage=[func|bb|edge]" << /*hasReplacement=*/true
975 << "-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc],["
976 "control-flow]";
977 }
978
979 // trace-pc w/o func/bb/edge implies edge.
980 if (!(CoverageFeatures & InsertionPointTypes)) {
981 if (CoverageFeatures & (CoverageTracePC | CoverageTracePCEntryExit |
984 CoverageFeatures |= CoverageEdge;
985
986 if (CoverageFeatures & CoverageStackDepth)
987 CoverageFeatures |= CoverageFunc;
988 }
989
990 // Parse -fsanitize-coverage-(allow|ignore)list options if coverage enabled.
991 // This also validates special case lists format.
992 // Here, OptSpecifier() acts as a never-matching command-line argument.
993 // So, there is no way to clear coverage lists but you can append to them.
994 if (CoverageFeatures) {
996 D, Args, CoverageAllowlistFiles,
997 options::OPT_fsanitize_coverage_allowlist, OptSpecifier(),
998 clang::diag::err_drv_malformed_sanitizer_coverage_allowlist,
999 DiagnoseErrors);
1001 D, Args, CoverageIgnorelistFiles,
1002 options::OPT_fsanitize_coverage_ignorelist, OptSpecifier(),
1003 clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist,
1004 DiagnoseErrors);
1005 }
1006
1007 // Parse -f(no-)?sanitize-metadata.
1008 for (const auto *Arg :
1009 Args.filtered(options::OPT_fexperimental_sanitize_metadata_EQ,
1010 options::OPT_fno_experimental_sanitize_metadata_EQ)) {
1011 if (Arg->getOption().matches(
1012 options::OPT_fexperimental_sanitize_metadata_EQ)) {
1013 Arg->claim();
1014 BinaryMetadataFeatures |=
1015 parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);
1016 } else {
1017 Arg->claim();
1018 BinaryMetadataFeatures &=
1019 ~parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);
1020 }
1021 }
1022
1023 // Parse -fsanitize-metadata-ignorelist option if enabled.
1024 if (BinaryMetadataFeatures) {
1026 D, Args, BinaryMetadataIgnorelistFiles,
1027 options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ,
1028 OptSpecifier(), // Cannot clear ignore list, only append.
1029 clang::diag::err_drv_malformed_sanitizer_metadata_ignorelist,
1030 DiagnoseErrors);
1031 }
1032
1033 SharedRuntime = Args.hasFlag(
1034 options::OPT_shared_libsan, options::OPT_static_libsan,
1035 TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() ||
1036 TC.getTriple().isOSDarwin() || TC.getTriple().isOSWindows());
1037 if (!SharedRuntime && TC.getTriple().isOSWindows()) {
1038 Arg *A =
1039 Args.getLastArg(options::OPT_shared_libsan, options::OPT_static_libsan);
1040 D.Diag(clang::diag::err_drv_unsupported_opt_for_target)
1041 << A->getSpelling() << TC.getTriple().str();
1042 }
1043
1044 ImplicitCfiRuntime = TC.getTriple().isAndroid();
1045
1046 if (AllAddedKinds & SanitizerKind::Address) {
1047 NeedPIE |= TC.getTriple().isOSFuchsia();
1048 if (Arg *A =
1049 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
1050 StringRef S = A->getValue();
1051 // Legal values are 0 and 1, 2, but in future we may add more levels.
1052 if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
1053 AsanFieldPadding > 2) &&
1054 DiagnoseErrors) {
1055 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
1056 }
1057 }
1058
1059 if (Arg *WindowsDebugRTArg =
1060 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
1061 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
1062 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
1063 switch (WindowsDebugRTArg->getOption().getID()) {
1064 case options::OPT__SLASH_MTd:
1065 case options::OPT__SLASH_MDd:
1066 case options::OPT__SLASH_LDd:
1067 if (DiagnoseErrors) {
1068 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
1069 << WindowsDebugRTArg->getAsString(Args)
1070 << lastArgumentForMask(D, Args, SanitizerKind::Address);
1071 D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
1072 }
1073 }
1074 }
1075
1076 StableABI = Args.hasFlag(options::OPT_fsanitize_stable_abi,
1077 options::OPT_fno_sanitize_stable_abi, false);
1078
1079 AsanPoisonCustomArrayCookie = Args.hasFlag(
1080 options::OPT_fsanitize_address_poison_custom_array_cookie,
1081 options::OPT_fno_sanitize_address_poison_custom_array_cookie,
1082 AsanPoisonCustomArrayCookie);
1083
1084 AsanOutlineInstrumentation =
1085 Args.hasFlag(options::OPT_fsanitize_address_outline_instrumentation,
1086 options::OPT_fno_sanitize_address_outline_instrumentation,
1087 AsanOutlineInstrumentation);
1088
1089 AsanGlobalsDeadStripping = Args.hasFlag(
1090 options::OPT_fsanitize_address_globals_dead_stripping,
1091 options::OPT_fno_sanitize_address_globals_dead_stripping, true);
1092
1093 // Enable ODR indicators which allow better handling of mixed instrumented
1094 // and uninstrumented globals. Disable them for Windows where weak odr
1095 // indicators (.weak.__odr_asan_gen*) may cause multiple definition linker
1096 // errors in the absence of -lldmingw.
1097 AsanUseOdrIndicator =
1098 Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
1099 options::OPT_fno_sanitize_address_use_odr_indicator,
1100 !TC.getTriple().isOSWindows());
1101
1102 if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) {
1103 AsanInvalidPointerCmp = true;
1104 }
1105
1106 if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) {
1107 AsanInvalidPointerSub = true;
1108 }
1109
1110 if (TC.getTriple().isOSDarwin() &&
1111 (Args.hasArg(options::OPT_mkernel) ||
1112 Args.hasArg(options::OPT_fapple_kext))) {
1113 AsanDtorKind = llvm::AsanDtorKind::None;
1114 }
1115
1116 if (const auto *Arg =
1117 Args.getLastArg(options::OPT_sanitize_address_destructor_EQ)) {
1118 auto parsedAsanDtorKind = AsanDtorKindFromString(Arg->getValue());
1119 if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid && DiagnoseErrors) {
1120 TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)
1121 << Arg->getSpelling() << Arg->getValue();
1122 }
1123 AsanDtorKind = parsedAsanDtorKind;
1124 }
1125
1126 if (const auto *Arg = Args.getLastArg(
1127 options::OPT_sanitize_address_use_after_return_EQ)) {
1128 auto parsedAsanUseAfterReturn =
1130 if (parsedAsanUseAfterReturn ==
1131 llvm::AsanDetectStackUseAfterReturnMode::Invalid &&
1132 DiagnoseErrors) {
1133 TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)
1134 << Arg->getSpelling() << Arg->getValue();
1135 }
1136 AsanUseAfterReturn = parsedAsanUseAfterReturn;
1137 }
1138
1139 } else {
1140 // -fsanitize=pointer-compare/pointer-subtract requires -fsanitize=address.
1141 SanitizerMask DetectInvalidPointerPairs =
1142 SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract;
1143 if ((AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) &&
1144 DiagnoseErrors) {
1145 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)
1146 << lastArgumentForMask(D, Args,
1147 SanitizerKind::PointerCompare |
1148 SanitizerKind::PointerSubtract)
1149 << "-fsanitize=address";
1150 }
1151 }
1152
1153 if (AllAddedKinds & (SanitizerKind::Address | SanitizerKind::KernelAddress)) {
1154 AsanUseAfterScope = Args.hasFlag(
1155 options::OPT_fsanitize_address_use_after_scope,
1156 options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);
1157 } else {
1158 AsanUseAfterScope = false;
1159 }
1160
1161 if (AllAddedKinds & SanitizerKind::HWAddress) {
1162 if (Arg *HwasanAbiArg =
1163 Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {
1164 HwasanAbi = HwasanAbiArg->getValue();
1165 if (HwasanAbi != "platform" && HwasanAbi != "interceptor" &&
1166 DiagnoseErrors)
1167 D.Diag(clang::diag::err_drv_invalid_value)
1168 << HwasanAbiArg->getAsString(Args) << HwasanAbi;
1169 } else {
1170 HwasanAbi = "interceptor";
1171 }
1172 if (TC.getTriple().getArch() == llvm::Triple::x86_64)
1173 HwasanUseAliases = Args.hasFlag(
1174 options::OPT_fsanitize_hwaddress_experimental_aliasing,
1175 options::OPT_fno_sanitize_hwaddress_experimental_aliasing,
1176 HwasanUseAliases);
1177 }
1178
1179 if (AllAddedKinds & SanitizerKind::SafeStack) {
1180 // SafeStack runtime is built into the system on Android and Fuchsia.
1181 SafeStackRuntime =
1182 !TC.getTriple().isAndroid() && !TC.getTriple().isOSFuchsia();
1183 }
1184
1185 if (AllAddedKinds & SanitizerKind::AllocToken) {
1186 AllocTokenFastABI = Args.hasFlag(
1187 options::OPT_fsanitize_alloc_token_fast_abi,
1188 options::OPT_fno_sanitize_alloc_token_fast_abi, AllocTokenFastABI);
1189 AllocTokenExtended = Args.hasFlag(
1190 options::OPT_fsanitize_alloc_token_extended,
1191 options::OPT_fno_sanitize_alloc_token_extended, AllocTokenExtended);
1192 }
1193
1194 if (AllAddedKinds & SanitizerKind::Type) {
1195 TysanOutlineInstrumentation =
1196 Args.hasFlag(options::OPT_fsanitize_type_outline_instrumentation,
1197 options::OPT_fno_sanitize_type_outline_instrumentation,
1198 TysanOutlineInstrumentation);
1199 }
1200
1201 LinkRuntimes = Args.hasFlag(options::OPT_fsanitize_link_runtime,
1202 options::OPT_fno_sanitize_link_runtime,
1203 !Args.hasArg(options::OPT_r));
1204
1205 // Parse -link-cxx-sanitizer flag.
1206 LinkCXXRuntimes = D.CCCIsCXX();
1207 LinkCXXRuntimes =
1208 Args.hasFlag(options::OPT_fsanitize_link_cxx_runtime,
1209 options::OPT_fno_sanitize_link_cxx_runtime, LinkCXXRuntimes);
1210
1211 NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile,
1212 options::OPT_fmemory_profile_EQ,
1213 options::OPT_fno_memory_profile, false);
1214
1215 // Finally, initialize the set of available and recoverable sanitizers.
1216 Sanitizers.Mask |= Kinds;
1217 RecoverableSanitizers.Mask |= RecoverableKinds;
1218 TrapSanitizers.Mask |= TrappingKinds;
1219 assert(!(RecoverableKinds & TrappingKinds) &&
1220 "Overlap between recoverable and trapping sanitizers");
1221
1222 MergeHandlers.Mask |= MergeKinds;
1223
1224 AnnotateDebugInfo.Mask |= AnnotateDebugInfoKinds;
1225 SuppressUBSanFeature.Mask |= IgnoreForUbsanFeature;
1226
1227 // Zero out SkipHotCutoffs for unused sanitizers
1228 SkipHotCutoffs.clear(~Sanitizers.Mask);
1229}
1230
1231static std::string toString(const clang::SanitizerSet &Sanitizers) {
1232 std::string Res;
1233#define SANITIZER(NAME, ID) \
1234 if (Sanitizers.has(SanitizerKind::ID)) { \
1235 if (!Res.empty()) \
1236 Res += ","; \
1237 Res += NAME; \
1238 }
1239#include "clang/Basic/Sanitizers.def"
1240 return Res;
1241}
1242
1243static std::string toString(const clang::SanitizerMaskCutoffs &Cutoffs) {
1245 serializeSanitizerMaskCutoffs(Cutoffs, Res);
1246 return llvm::join(Res, ",");
1247}
1248
1249static std::string toStringWithGroups(const clang::SanitizerSet &Sanitizers) {
1250 std::string Res;
1251#define SANITIZER(NAME, ID) \
1252 if (Sanitizers.has(SanitizerKind::ID)) { \
1253 if (!Res.empty()) \
1254 Res += ","; \
1255 Res += NAME; \
1256 }
1257#define SANITIZER_GROUP(NAME, ID, ALIAS) SANITIZER(NAME, ID##Group)
1258#include "clang/Basic/Sanitizers.def"
1259 return Res;
1260}
1261
1262static void addSpecialCaseListOpt(const llvm::opt::ArgList &Args,
1263 llvm::opt::ArgStringList &CmdArgs,
1264 const char *SCLOptFlag,
1265 const std::vector<std::string> &SCLFiles) {
1266 for (const auto &SCLPath : SCLFiles) {
1267 SmallString<64> SCLOpt(SCLOptFlag);
1268 SCLOpt += SCLPath;
1269 CmdArgs.push_back(Args.MakeArgString(SCLOpt));
1270 }
1271}
1272
1273static void addIncludeLinkerOption(const ToolChain &TC,
1274 const llvm::opt::ArgList &Args,
1275 llvm::opt::ArgStringList &CmdArgs,
1276 StringRef SymbolName) {
1277 SmallString<64> LinkerOptionFlag;
1278 LinkerOptionFlag = "--linker-option=/include:";
1279 if (TC.getTriple().getArch() == llvm::Triple::x86) {
1280 // Win32 mangles C function names with a '_' prefix.
1281 LinkerOptionFlag += '_';
1282 }
1283 LinkerOptionFlag += SymbolName;
1284 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
1285}
1286
1287static bool hasTargetFeatureMTE(const llvm::opt::ArgStringList &CmdArgs) {
1288 for (auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End;
1289 ++Start) {
1290 auto It = std::find(Start, End, StringRef("+mte"));
1291 if (It == End)
1292 break;
1293 if (It > Start && *std::prev(It) == StringRef("-target-feature"))
1294 return true;
1295 Start = It;
1296 }
1297 return false;
1298}
1299
1300void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
1301 llvm::opt::ArgStringList &CmdArgs,
1302 types::ID InputType) const {
1303 // NVPTX doesn't currently support sanitizers. Bailing out here means
1304 // that e.g. -fsanitize=address applies only to host code, which is what we
1305 // want for now.
1306 if (TC.getTriple().isNVPTX())
1307 return;
1308 // AMDGPU sanitizer support is experimental and controlled by -fgpu-sanitize.
1309 bool GPUSanitize = false;
1310 if (TC.getTriple().isAMDGPU()) {
1311 if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
1312 true))
1313 return;
1314 GPUSanitize = true;
1315 }
1316
1317 // Translate available CoverageFeatures to corresponding clang-cc1 flags.
1318 // Do it even if Sanitizers.empty() since some forms of coverage don't require
1319 // sanitizers.
1320 std::pair<int, const char *> CoverageFlags[] = {
1321 std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"),
1322 std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"),
1323 std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"),
1324 std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"),
1325 std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"),
1326 std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"),
1327 std::make_pair(CoverageTraceDiv, "-fsanitize-coverage-trace-div"),
1328 std::make_pair(CoverageTraceGep, "-fsanitize-coverage-trace-gep"),
1329 std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"),
1330 std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"),
1331 std::make_pair(CoverageTracePCEntryExit,
1332 "-fsanitize-coverage-trace-pc-entry-exit"),
1333 std::make_pair(CoverageTracePCGuard,
1334 "-fsanitize-coverage-trace-pc-guard"),
1335 std::make_pair(CoverageInline8bitCounters,
1336 "-fsanitize-coverage-inline-8bit-counters"),
1337 std::make_pair(CoverageInlineBoolFlag,
1338 "-fsanitize-coverage-inline-bool-flag"),
1339 std::make_pair(CoveragePCTable, "-fsanitize-coverage-pc-table"),
1340 std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune"),
1341 std::make_pair(CoverageStackDepth, "-fsanitize-coverage-stack-depth"),
1342 std::make_pair(CoverageTraceLoads, "-fsanitize-coverage-trace-loads"),
1343 std::make_pair(CoverageTraceStores, "-fsanitize-coverage-trace-stores"),
1344 std::make_pair(CoverageControlFlow, "-fsanitize-coverage-control-flow")};
1345 for (auto F : CoverageFlags) {
1346 if (CoverageFeatures & F.first)
1347 CmdArgs.push_back(F.second);
1348 }
1350 Args, CmdArgs, "-fsanitize-coverage-allowlist=", CoverageAllowlistFiles);
1351 addSpecialCaseListOpt(Args, CmdArgs, "-fsanitize-coverage-ignorelist=",
1352 CoverageIgnorelistFiles);
1353
1354 if (CoverageStackDepthCallbackMin)
1355 CmdArgs.push_back(
1356 Args.MakeArgString("-fsanitize-coverage-stack-depth-callback-min=" +
1357 Twine(CoverageStackDepthCallbackMin)));
1358
1359 if (!GPUSanitize) {
1360 // Translate available BinaryMetadataFeatures to corresponding clang-cc1
1361 // flags. Does not depend on any other sanitizers. Unsupported on GPUs.
1362 const std::pair<int, std::string> BinaryMetadataFlags[] = {
1363 std::make_pair(BinaryMetadataCovered, "covered"),
1364 std::make_pair(BinaryMetadataAtomics, "atomics"),
1365 std::make_pair(BinaryMetadataUAR, "uar")};
1366 for (const auto &F : BinaryMetadataFlags) {
1367 if (BinaryMetadataFeatures & F.first)
1368 CmdArgs.push_back(
1369 Args.MakeArgString("-fexperimental-sanitize-metadata=" + F.second));
1370 }
1371 addSpecialCaseListOpt(Args, CmdArgs,
1372 "-fexperimental-sanitize-metadata-ignorelist=",
1373 BinaryMetadataIgnorelistFiles);
1374 }
1375
1376 if (TC.getTriple().isOSWindows() && needsUbsanRt() &&
1377 Args.hasFlag(options::OPT_frtlib_defaultlib,
1378 options::OPT_fno_rtlib_defaultlib, true)) {
1379 // Instruct the code generator to embed linker directives in the object file
1380 // that cause the required runtime libraries to be linked.
1381 CmdArgs.push_back(
1382 Args.MakeArgString("--dependent-lib=" +
1383 TC.getCompilerRTBasename(Args, "ubsan_standalone")));
1384 if (types::isCXX(InputType))
1385 CmdArgs.push_back(Args.MakeArgString(
1386 "--dependent-lib=" +
1387 TC.getCompilerRTBasename(Args, "ubsan_standalone_cxx")));
1388 }
1389 if (TC.getTriple().isOSWindows() && needsStatsRt() &&
1390 Args.hasFlag(options::OPT_frtlib_defaultlib,
1391 options::OPT_fno_rtlib_defaultlib, true)) {
1392 CmdArgs.push_back(Args.MakeArgString(
1393 "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats_client")));
1394
1395 // The main executable must export the stats runtime.
1396 // FIXME: Only exporting from the main executable (e.g. based on whether the
1397 // translation unit defines main()) would save a little space, but having
1398 // multiple copies of the runtime shouldn't hurt.
1399 CmdArgs.push_back(Args.MakeArgString(
1400 "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats")));
1401 addIncludeLinkerOption(TC, Args, CmdArgs, "__sanitizer_stats_register");
1402 }
1403
1404 if (Sanitizers.empty())
1405 return;
1406 CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers)));
1407
1408 if (!SuppressUBSanFeature.empty())
1409 CmdArgs.push_back(
1410 Args.MakeArgString("-fsanitize-ignore-for-ubsan-feature=" +
1411 toString(SuppressUBSanFeature)));
1412
1413 if (!RecoverableSanitizers.empty())
1414 CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" +
1415 toString(RecoverableSanitizers)));
1416
1417 if (!TrapSanitizers.empty())
1418 CmdArgs.push_back(
1419 Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));
1420
1421 if (!MergeHandlers.empty())
1422 CmdArgs.push_back(
1423 Args.MakeArgString("-fsanitize-merge=" + toString(MergeHandlers)));
1424
1425 std::string SkipHotCutoffsStr = toString(SkipHotCutoffs);
1426 if (!SkipHotCutoffsStr.empty())
1427 CmdArgs.push_back(
1428 Args.MakeArgString("-fsanitize-skip-hot-cutoff=" + SkipHotCutoffsStr));
1429
1430 if (!AnnotateDebugInfo.empty())
1431 CmdArgs.push_back(Args.MakeArgString("-fsanitize-annotate-debug-info=" +
1432 toString(AnnotateDebugInfo)));
1433
1434 Args.AddLastArg(CmdArgs, options::OPT_fsanitize_debug_trap_reasons_EQ);
1435
1436 addSpecialCaseListOpt(Args, CmdArgs,
1437 "-fsanitize-ignorelist=", UserIgnorelistFiles);
1438 addSpecialCaseListOpt(Args, CmdArgs,
1439 "-fsanitize-system-ignorelist=", SystemIgnorelistFiles);
1440
1441 if (OverflowPatternExclusions)
1442 Args.AddAllArgs(
1443 CmdArgs, options::OPT_fsanitize_undefined_ignore_overflow_pattern_EQ);
1444
1445 if (MsanTrackOrigins)
1446 CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" +
1447 Twine(MsanTrackOrigins)));
1448
1449 if (MsanUseAfterDtor)
1450 CmdArgs.push_back("-fsanitize-memory-use-after-dtor");
1451
1452 if (!MsanParamRetval)
1453 CmdArgs.push_back("-fno-sanitize-memory-param-retval");
1454
1455 // FIXME: Pass these parameters as function attributes, not as -llvm flags.
1456 if (!TsanMemoryAccess) {
1457 CmdArgs.push_back("-mllvm");
1458 CmdArgs.push_back("-tsan-instrument-memory-accesses=0");
1459 CmdArgs.push_back("-mllvm");
1460 CmdArgs.push_back("-tsan-instrument-memintrinsics=0");
1461 }
1462 if (!TsanFuncEntryExit) {
1463 CmdArgs.push_back("-mllvm");
1464 CmdArgs.push_back("-tsan-instrument-func-entry-exit=0");
1465 }
1466 if (!TsanAtomics) {
1467 CmdArgs.push_back("-mllvm");
1468 CmdArgs.push_back("-tsan-instrument-atomics=0");
1469 }
1470
1471 if (HwasanUseAliases) {
1472 CmdArgs.push_back("-mllvm");
1473 CmdArgs.push_back("-hwasan-experimental-use-page-aliases=1");
1474 }
1475
1476 if (CfiCrossDso)
1477 CmdArgs.push_back("-fsanitize-cfi-cross-dso");
1478
1479 if (CfiICallGeneralizePointers)
1480 CmdArgs.push_back("-fsanitize-cfi-icall-generalize-pointers");
1481
1482 if (CfiICallNormalizeIntegers)
1483 CmdArgs.push_back("-fsanitize-cfi-icall-experimental-normalize-integers");
1484
1485 if (KcfiArity) {
1486 if (!TC.getTriple().isOSLinux() || !TC.getTriple().isArch64Bit()) {
1487 TC.getDriver().Diag(clang::diag::err_drv_kcfi_arity_unsupported_target)
1488 << TC.getTriple().str();
1489 }
1490 CmdArgs.push_back("-fsanitize-kcfi-arity");
1491 }
1492
1493 if (CfiCanonicalJumpTables)
1494 CmdArgs.push_back("-fsanitize-cfi-canonical-jump-tables");
1495
1496 if (Stats)
1497 CmdArgs.push_back("-fsanitize-stats");
1498
1499 if (MinimalRuntime)
1500 CmdArgs.push_back("-fsanitize-minimal-runtime");
1501
1502 if (TrapLoop)
1503 CmdArgs.push_back("-fsanitize-trap-loop");
1504
1505 if (HandlerPreserveAllRegs)
1506 CmdArgs.push_back("-fsanitize-handler-preserve-all-regs");
1507
1508 if (AsanFieldPadding)
1509 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" +
1510 Twine(AsanFieldPadding)));
1511
1512 if (AsanUseAfterScope)
1513 CmdArgs.push_back("-fsanitize-address-use-after-scope");
1514
1515 if (AsanPoisonCustomArrayCookie)
1516 CmdArgs.push_back("-fsanitize-address-poison-custom-array-cookie");
1517
1518 if (AsanGlobalsDeadStripping)
1519 CmdArgs.push_back("-fsanitize-address-globals-dead-stripping");
1520
1521 if (!AsanUseOdrIndicator)
1522 CmdArgs.push_back("-fno-sanitize-address-use-odr-indicator");
1523
1524 if (AsanInvalidPointerCmp) {
1525 CmdArgs.push_back("-mllvm");
1526 CmdArgs.push_back("-asan-detect-invalid-pointer-cmp");
1527 }
1528
1529 if (AsanInvalidPointerSub) {
1530 CmdArgs.push_back("-mllvm");
1531 CmdArgs.push_back("-asan-detect-invalid-pointer-sub");
1532 }
1533
1534 if (AsanOutlineInstrumentation) {
1535 CmdArgs.push_back("-mllvm");
1536 CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");
1537 }
1538
1539 if (!TysanOutlineInstrumentation) {
1540 CmdArgs.push_back("-mllvm");
1541 CmdArgs.push_back("-tysan-outline-instrumentation=false");
1542 }
1543
1544 // When emitting Stable ABI instrumentation, force outlining calls and avoid
1545 // inlining shadow memory poisoning. While this is a big performance burden
1546 // for now it allows full abstraction from implementation details.
1547 if (StableABI) {
1548 CmdArgs.push_back("-mllvm");
1549 CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");
1550 CmdArgs.push_back("-mllvm");
1551 CmdArgs.push_back("-asan-max-inline-poisoning-size=0");
1552 CmdArgs.push_back("-mllvm");
1553 CmdArgs.push_back("-asan-guard-against-version-mismatch=0");
1554 }
1555
1556 // Only pass the option to the frontend if the user requested,
1557 // otherwise the frontend will just use the codegen default.
1558 if (AsanDtorKind != llvm::AsanDtorKind::Invalid) {
1559 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-destructor=" +
1560 AsanDtorKindToString(AsanDtorKind)));
1561 }
1562
1563 if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
1564 CmdArgs.push_back(Args.MakeArgString(
1565 "-fsanitize-address-use-after-return=" +
1566 AsanDetectStackUseAfterReturnModeToString(AsanUseAfterReturn)));
1567 }
1568
1569 if (!HwasanAbi.empty()) {
1570 CmdArgs.push_back("-default-function-attr");
1571 CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi));
1572 }
1573
1574 if (Sanitizers.has(SanitizerKind::HWAddress) && !HwasanUseAliases) {
1575 CmdArgs.push_back("-target-feature");
1576 CmdArgs.push_back("+tagged-globals");
1577 }
1578
1579 // MSan: Workaround for PR16386.
1580 // ASan: This is mainly to help LSan with cases such as
1581 // https://github.com/google/sanitizers/issues/373
1582 // We can't make this conditional on -fsanitize=leak, as that flag shouldn't
1583 // affect compilation.
1584 if (Sanitizers.has(SanitizerKind::Memory) ||
1585 Sanitizers.has(SanitizerKind::Address))
1586 CmdArgs.push_back("-fno-assume-sane-operator-new");
1587
1588 // Flags for -fsanitize=alloc-token.
1589 if (AllocTokenFastABI)
1590 CmdArgs.push_back("-fsanitize-alloc-token-fast-abi");
1591 if (AllocTokenExtended)
1592 CmdArgs.push_back("-fsanitize-alloc-token-extended");
1593
1594 // libFuzzer wants to intercept calls to certain library functions, so the
1595 // following -fno-builtin-* flags force the compiler to emit interposable
1596 // libcalls to these functions. Other sanitizers effectively do the same thing
1597 // by marking all library call sites with NoBuiltin attribute in their LLVM
1598 // pass. (see llvm::maybeMarkSanitizerLibraryCallNoBuiltin)
1599 if (Sanitizers.has(SanitizerKind::FuzzerNoLink)) {
1600 CmdArgs.push_back("-fno-builtin-bcmp");
1601 CmdArgs.push_back("-fno-builtin-memcmp");
1602 CmdArgs.push_back("-fno-builtin-strncmp");
1603 CmdArgs.push_back("-fno-builtin-strcmp");
1604 CmdArgs.push_back("-fno-builtin-strncasecmp");
1605 CmdArgs.push_back("-fno-builtin-strcasecmp");
1606 CmdArgs.push_back("-fno-builtin-strstr");
1607 CmdArgs.push_back("-fno-builtin-strcasestr");
1608 CmdArgs.push_back("-fno-builtin-memmem");
1609 }
1610
1611 // Require -fvisibility= flag on non-Windows when compiling if vptr CFI is
1612 // enabled.
1613 if (Sanitizers.hasOneOf(CFIClasses) && !TC.getTriple().isOSWindows() &&
1614 !Args.hasArg(options::OPT_fvisibility_EQ)) {
1615 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)
1616 << lastArgumentForMask(TC.getDriver(), Args,
1617 Sanitizers.Mask & CFIClasses)
1618 << "-fvisibility=";
1619 }
1620
1621 if (Sanitizers.has(SanitizerKind::MemtagStack) &&
1622 !hasTargetFeatureMTE(CmdArgs))
1623 TC.getDriver().Diag(diag::err_stack_tagging_requires_hardware_feature);
1624}
1625
1626SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
1627 bool DiagnoseErrors) {
1628 assert(
1629 (A->getOption().matches(options::OPT_fsanitize_EQ) ||
1630 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
1631 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
1632 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
1633 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
1634 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ) ||
1635 A->getOption().matches(options::OPT_fsanitize_merge_handlers_EQ) ||
1636 A->getOption().matches(options::OPT_fno_sanitize_merge_handlers_EQ) ||
1637 A->getOption().matches(options::OPT_fsanitize_annotate_debug_info_EQ) ||
1638 A->getOption().matches(
1639 options::OPT_fno_sanitize_annotate_debug_info_EQ) ||
1640 A->getOption().matches(
1641 options::OPT_fsanitize_ignore_for_ubsan_feature_EQ)) &&
1642 "Invalid argument in parseArgValues!");
1643 SanitizerMask Kinds;
1644 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1645 const char *Value = A->getValue(i);
1646 SanitizerMask Kind;
1647 // Special case: don't accept -fsanitize=all.
1648 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
1649 0 == strcmp("all", Value))
1650 Kind = SanitizerMask();
1651 else
1652 Kind = parseSanitizerValue(Value, /*AllowGroups=*/true);
1653
1654 if (Kind)
1655 Kinds |= Kind;
1656 else if (DiagnoseErrors)
1657 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1658 << A->getSpelling() << Value;
1659 }
1660 return Kinds;
1661}
1662
1663void parseArgCutoffs(const Driver &D, const llvm::opt::Arg *A,
1664 bool DiagnoseErrors, SanitizerMaskCutoffs &Cutoffs) {
1665 assert(A->getOption().matches(options::OPT_fsanitize_skip_hot_cutoff_EQ) &&
1666 "Invalid argument in parseArgCutoffs!");
1667 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1668 const char *Value = A->getValue(i);
1669
1670 // We don't check the value of Cutoffs[i]: it's legal to specify
1671 // a cutoff of 0.
1672 if (!parseSanitizerWeightedValue(Value, /*AllowGroups=*/true, Cutoffs) &&
1673 DiagnoseErrors)
1674 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1675 << A->getSpelling() << Value;
1676 }
1677}
1678
1680 const llvm::opt::Arg *A,
1681 bool DiagnoseErrors) {
1682 int Exclusions = 0;
1683 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1684 const char *Value = A->getValue(i);
1685 int E =
1686 llvm::StringSwitch<int>(Value)
1687 .Case("none", LangOptionsBase::None)
1688 .Case("all", LangOptionsBase::All)
1689 .Case("add-unsigned-overflow-test",
1691 .Case("add-signed-overflow-test",
1693 .Case("negated-unsigned-const", LangOptionsBase::NegUnsignedConst)
1694 .Case("unsigned-post-decr-while", LangOptionsBase::PostDecrInWhile)
1695 .Default(0);
1696 if (E == 0)
1697 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1698 << A->getSpelling() << Value;
1699 Exclusions |= E;
1700 }
1701 return Exclusions;
1702}
1703
1704int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A,
1705 bool DiagnoseErrors) {
1706 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
1707 A->getOption().matches(options::OPT_fno_sanitize_coverage));
1708 int Features = 0;
1709 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1710 const char *Value = A->getValue(i);
1711 int F = llvm::StringSwitch<int>(Value)
1712 .Case("func", CoverageFunc)
1713 .Case("bb", CoverageBB)
1714 .Case("edge", CoverageEdge)
1715 .Case("indirect-calls", CoverageIndirCall)
1716 .Case("trace-bb", CoverageTraceBB)
1717 .Case("trace-cmp", CoverageTraceCmp)
1718 .Case("trace-div", CoverageTraceDiv)
1719 .Case("trace-gep", CoverageTraceGep)
1720 .Case("8bit-counters", Coverage8bitCounters)
1721 .Case("trace-pc", CoverageTracePC)
1722 .Case("trace-pc-entry-exit", CoverageTracePCEntryExit)
1723 .Case("trace-pc-guard", CoverageTracePCGuard)
1724 .Case("no-prune", CoverageNoPrune)
1725 .Case("inline-8bit-counters", CoverageInline8bitCounters)
1726 .Case("inline-bool-flag", CoverageInlineBoolFlag)
1727 .Case("pc-table", CoveragePCTable)
1728 .Case("stack-depth", CoverageStackDepth)
1729 .Case("trace-loads", CoverageTraceLoads)
1730 .Case("trace-stores", CoverageTraceStores)
1731 .Case("control-flow", CoverageControlFlow)
1732 .Default(0);
1733 if (F == 0 && DiagnoseErrors)
1734 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1735 << A->getSpelling() << Value;
1736 Features |= F;
1737 }
1738 return Features;
1739}
1740
1741int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A,
1742 bool DiagnoseErrors) {
1743 assert(
1744 A->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ) ||
1745 A->getOption().matches(
1746 options::OPT_fno_experimental_sanitize_metadata_EQ));
1747 int Features = 0;
1748 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1749 const char *Value = A->getValue(i);
1750 int F = llvm::StringSwitch<int>(Value)
1751 .Case("covered", BinaryMetadataCovered)
1752 .Case("atomics", BinaryMetadataAtomics)
1753 .Case("uar", BinaryMetadataUAR)
1754 .Case("all", ~0)
1755 .Default(0);
1756 if (F == 0 && DiagnoseErrors)
1757 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1758 << A->getSpelling() << Value;
1759 Features |= F;
1760 }
1761 return Features;
1762}
1763
1764std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,
1765 SanitizerMask Mask) {
1766 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
1767 E = Args.rend();
1768 I != E; ++I) {
1769 const auto *Arg = *I;
1770 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
1771 SanitizerMask AddKinds =
1772 expandSanitizerGroups(parseArgValues(D, Arg, false));
1773 if (AddKinds & Mask)
1774 return describeSanitizeArg(Arg, Mask);
1775 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
1776 SanitizerMask RemoveKinds =
1777 expandSanitizerGroups(parseArgValues(D, Arg, false));
1778 Mask &= ~RemoveKinds;
1779 }
1780 }
1781 llvm_unreachable("arg list didn't provide expected value");
1782}
1783
1784std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask) {
1785 assert(A->getOption().matches(options::OPT_fsanitize_EQ) &&
1786 "Invalid argument in describeSanitizerArg!");
1787
1788 std::string Sanitizers;
1789 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1791 parseSanitizerValue(A->getValue(i), /*AllowGroups=*/true)) &
1792 Mask) {
1793 if (!Sanitizers.empty())
1794 Sanitizers += ",";
1795 Sanitizers += A->getValue(i);
1796 }
1797 }
1798
1799 assert(!Sanitizers.empty() && "arg didn't provide expected value");
1800 return "-fsanitize=" + Sanitizers;
1801}
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:261
RTTIMode getRTTIMode() const
Definition ToolChain.h:335
const llvm::opt::Arg * getRTTIArg() const
Definition ToolChain.h:332
const llvm::Triple & getTriple() const
Definition ToolChain.h:263
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:834
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