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