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