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