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