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