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