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