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