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