150
|
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/StringSwitch.h"
|
|
17 #include "llvm/Support/FileSystem.h"
|
|
18 #include "llvm/Support/Path.h"
|
|
19 #include "llvm/Support/SpecialCaseList.h"
|
|
20 #include "llvm/Support/TargetParser.h"
|
|
21 #include <memory>
|
|
22
|
|
23 using namespace clang;
|
|
24 using namespace clang::driver;
|
|
25 using namespace llvm::opt;
|
|
26
|
|
27 static const SanitizerMask NeedsUbsanRt =
|
|
28 SanitizerKind::Undefined | SanitizerKind::Integer |
|
|
29 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
|
|
30 SanitizerKind::CFI | SanitizerKind::FloatDivideByZero;
|
|
31 static const SanitizerMask NeedsUbsanCxxRt =
|
|
32 SanitizerKind::Vptr | SanitizerKind::CFI;
|
|
33 static const SanitizerMask NotAllowedWithTrap = SanitizerKind::Vptr;
|
|
34 static const SanitizerMask NotAllowedWithMinimalRuntime =
|
|
35 SanitizerKind::Function | SanitizerKind::Vptr;
|
|
36 static const SanitizerMask RequiresPIE =
|
|
37 SanitizerKind::DataFlow | SanitizerKind::HWAddress | SanitizerKind::Scudo;
|
|
38 static const SanitizerMask NeedsUnwindTables =
|
|
39 SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Thread |
|
|
40 SanitizerKind::Memory | SanitizerKind::DataFlow;
|
|
41 static const SanitizerMask SupportsCoverage =
|
|
42 SanitizerKind::Address | SanitizerKind::HWAddress |
|
|
43 SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |
|
|
44 SanitizerKind::MemTag | SanitizerKind::Memory |
|
|
45 SanitizerKind::KernelMemory | SanitizerKind::Leak |
|
|
46 SanitizerKind::Undefined | SanitizerKind::Integer |
|
|
47 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
|
|
48 SanitizerKind::DataFlow | SanitizerKind::Fuzzer |
|
|
49 SanitizerKind::FuzzerNoLink | SanitizerKind::FloatDivideByZero |
|
|
50 SanitizerKind::SafeStack | SanitizerKind::ShadowCallStack;
|
|
51 static const SanitizerMask RecoverableByDefault =
|
|
52 SanitizerKind::Undefined | SanitizerKind::Integer |
|
|
53 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
|
|
54 SanitizerKind::FloatDivideByZero;
|
|
55 static const SanitizerMask Unrecoverable =
|
|
56 SanitizerKind::Unreachable | SanitizerKind::Return;
|
|
57 static const SanitizerMask AlwaysRecoverable =
|
|
58 SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress;
|
|
59 static const SanitizerMask NeedsLTO = SanitizerKind::CFI;
|
|
60 static const SanitizerMask TrappingSupported =
|
|
61 (SanitizerKind::Undefined & ~SanitizerKind::Vptr) |
|
|
62 SanitizerKind::UnsignedIntegerOverflow | SanitizerKind::ImplicitConversion |
|
|
63 SanitizerKind::Nullability | SanitizerKind::LocalBounds |
|
|
64 SanitizerKind::CFI | SanitizerKind::FloatDivideByZero;
|
|
65 static const SanitizerMask TrappingDefault = SanitizerKind::CFI;
|
|
66 static const SanitizerMask CFIClasses =
|
|
67 SanitizerKind::CFIVCall | SanitizerKind::CFINVCall |
|
|
68 SanitizerKind::CFIMFCall | SanitizerKind::CFIDerivedCast |
|
|
69 SanitizerKind::CFIUnrelatedCast;
|
|
70 static const SanitizerMask CompatibleWithMinimalRuntime =
|
173
|
71 TrappingSupported | SanitizerKind::Scudo | SanitizerKind::ShadowCallStack |
|
|
72 SanitizerKind::MemTag;
|
150
|
73
|
|
74 enum CoverageFeature {
|
|
75 CoverageFunc = 1 << 0,
|
|
76 CoverageBB = 1 << 1,
|
|
77 CoverageEdge = 1 << 2,
|
|
78 CoverageIndirCall = 1 << 3,
|
173
|
79 CoverageTraceBB = 1 << 4, // Deprecated.
|
150
|
80 CoverageTraceCmp = 1 << 5,
|
|
81 CoverageTraceDiv = 1 << 6,
|
|
82 CoverageTraceGep = 1 << 7,
|
173
|
83 Coverage8bitCounters = 1 << 8, // Deprecated.
|
150
|
84 CoverageTracePC = 1 << 9,
|
|
85 CoverageTracePCGuard = 1 << 10,
|
|
86 CoverageNoPrune = 1 << 11,
|
|
87 CoverageInline8bitCounters = 1 << 12,
|
|
88 CoveragePCTable = 1 << 13,
|
|
89 CoverageStackDepth = 1 << 14,
|
173
|
90 CoverageInlineBoolFlag = 1 << 15,
|
150
|
91 };
|
|
92
|
|
93 /// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
|
|
94 /// invalid components. Returns a SanitizerMask.
|
|
95 static SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
|
|
96 bool DiagnoseErrors);
|
|
97
|
|
98 /// Parse -f(no-)?sanitize-coverage= flag values, diagnosing any invalid
|
|
99 /// components. Returns OR of members of \c CoverageFeature enumeration.
|
|
100 static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A);
|
|
101
|
|
102 /// Produce an argument string from ArgList \p Args, which shows how it
|
|
103 /// provides some sanitizer kind from \p Mask. For example, the argument list
|
|
104 /// "-fsanitize=thread,vptr -fsanitize=address" with mask \c NeedsUbsanRt
|
|
105 /// would produce "-fsanitize=vptr".
|
|
106 static std::string lastArgumentForMask(const Driver &D,
|
|
107 const llvm::opt::ArgList &Args,
|
|
108 SanitizerMask Mask);
|
|
109
|
|
110 /// Produce an argument string from argument \p A, which shows how it provides
|
|
111 /// a value in \p Mask. For instance, the argument
|
|
112 /// "-fsanitize=address,alignment" with mask \c NeedsUbsanRt would produce
|
|
113 /// "-fsanitize=alignment".
|
|
114 static std::string describeSanitizeArg(const llvm::opt::Arg *A,
|
|
115 SanitizerMask Mask);
|
|
116
|
|
117 /// Produce a string containing comma-separated names of sanitizers in \p
|
|
118 /// Sanitizers set.
|
|
119 static std::string toString(const clang::SanitizerSet &Sanitizers);
|
|
120
|
173
|
121 static void validateSpecialCaseListFormat(const Driver &D,
|
|
122 std::vector<std::string> &SCLFiles,
|
|
123 unsigned MalformedSCLErrorDiagID) {
|
|
124 if (SCLFiles.empty())
|
|
125 return;
|
|
126
|
|
127 std::string BLError;
|
|
128 std::unique_ptr<llvm::SpecialCaseList> SCL(
|
|
129 llvm::SpecialCaseList::create(SCLFiles, D.getVFS(), BLError));
|
|
130 if (!SCL.get())
|
|
131 D.Diag(MalformedSCLErrorDiagID) << BLError;
|
|
132 }
|
|
133
|
150
|
134 static void addDefaultBlacklists(const Driver &D, SanitizerMask Kinds,
|
|
135 std::vector<std::string> &BlacklistFiles) {
|
|
136 struct Blacklist {
|
|
137 const char *File;
|
|
138 SanitizerMask Mask;
|
|
139 } Blacklists[] = {{"asan_blacklist.txt", SanitizerKind::Address},
|
|
140 {"hwasan_blacklist.txt", SanitizerKind::HWAddress},
|
|
141 {"memtag_blacklist.txt", SanitizerKind::MemTag},
|
|
142 {"msan_blacklist.txt", SanitizerKind::Memory},
|
|
143 {"tsan_blacklist.txt", SanitizerKind::Thread},
|
|
144 {"dfsan_abilist.txt", SanitizerKind::DataFlow},
|
|
145 {"cfi_blacklist.txt", SanitizerKind::CFI},
|
|
146 {"ubsan_blacklist.txt",
|
|
147 SanitizerKind::Undefined | SanitizerKind::Integer |
|
|
148 SanitizerKind::Nullability |
|
|
149 SanitizerKind::FloatDivideByZero}};
|
|
150
|
|
151 for (auto BL : Blacklists) {
|
|
152 if (!(Kinds & BL.Mask))
|
|
153 continue;
|
|
154
|
|
155 clang::SmallString<64> Path(D.ResourceDir);
|
|
156 llvm::sys::path::append(Path, "share", BL.File);
|
|
157 if (D.getVFS().exists(Path))
|
|
158 BlacklistFiles.push_back(std::string(Path.str()));
|
|
159 else if (BL.Mask == SanitizerKind::CFI)
|
|
160 // If cfi_blacklist.txt cannot be found in the resource dir, driver
|
|
161 // should fail.
|
|
162 D.Diag(clang::diag::err_drv_no_such_file) << Path;
|
|
163 }
|
173
|
164 validateSpecialCaseListFormat(
|
|
165 D, BlacklistFiles, clang::diag::err_drv_malformed_sanitizer_blacklist);
|
|
166 }
|
|
167
|
|
168 /// Parse -f(no-)?sanitize-(coverage-)?(white|black)list argument's values,
|
|
169 /// diagnosing any invalid file paths and validating special case list format.
|
|
170 static void parseSpecialCaseListArg(const Driver &D,
|
|
171 const llvm::opt::ArgList &Args,
|
|
172 std::vector<std::string> &SCLFiles,
|
|
173 llvm::opt::OptSpecifier SCLOptionID,
|
|
174 llvm::opt::OptSpecifier NoSCLOptionID,
|
|
175 unsigned MalformedSCLErrorDiagID) {
|
|
176 for (const auto *Arg : Args) {
|
|
177 // Match -fsanitize-(coverage-)?(white|black)list.
|
|
178 if (Arg->getOption().matches(SCLOptionID)) {
|
|
179 Arg->claim();
|
|
180 std::string SCLPath = Arg->getValue();
|
|
181 if (D.getVFS().exists(SCLPath)) {
|
|
182 SCLFiles.push_back(SCLPath);
|
|
183 } else {
|
|
184 D.Diag(clang::diag::err_drv_no_such_file) << SCLPath;
|
|
185 }
|
|
186 // Match -fno-sanitize-blacklist.
|
|
187 } else if (Arg->getOption().matches(NoSCLOptionID)) {
|
|
188 Arg->claim();
|
|
189 SCLFiles.clear();
|
|
190 }
|
|
191 }
|
|
192 validateSpecialCaseListFormat(D, SCLFiles, MalformedSCLErrorDiagID);
|
150
|
193 }
|
|
194
|
|
195 /// Sets group bits for every group that has at least one representative already
|
|
196 /// enabled in \p Kinds.
|
|
197 static SanitizerMask setGroupBits(SanitizerMask Kinds) {
|
|
198 #define SANITIZER(NAME, ID)
|
|
199 #define SANITIZER_GROUP(NAME, ID, ALIAS) \
|
|
200 if (Kinds & SanitizerKind::ID) \
|
|
201 Kinds |= SanitizerKind::ID##Group;
|
|
202 #include "clang/Basic/Sanitizers.def"
|
|
203 return Kinds;
|
|
204 }
|
|
205
|
|
206 static SanitizerMask parseSanitizeTrapArgs(const Driver &D,
|
|
207 const llvm::opt::ArgList &Args) {
|
|
208 SanitizerMask TrapRemove; // During the loop below, the accumulated set of
|
|
209 // sanitizers disabled by the current sanitizer
|
|
210 // argument or any argument after it.
|
|
211 SanitizerMask TrappingKinds;
|
|
212 SanitizerMask TrappingSupportedWithGroups = setGroupBits(TrappingSupported);
|
|
213
|
|
214 for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
|
|
215 I != E; ++I) {
|
|
216 const auto *Arg = *I;
|
|
217 if (Arg->getOption().matches(options::OPT_fsanitize_trap_EQ)) {
|
|
218 Arg->claim();
|
|
219 SanitizerMask Add = parseArgValues(D, Arg, true);
|
|
220 Add &= ~TrapRemove;
|
|
221 if (SanitizerMask InvalidValues = Add & ~TrappingSupportedWithGroups) {
|
|
222 SanitizerSet S;
|
|
223 S.Mask = InvalidValues;
|
|
224 D.Diag(diag::err_drv_unsupported_option_argument) << "-fsanitize-trap"
|
|
225 << toString(S);
|
|
226 }
|
|
227 TrappingKinds |= expandSanitizerGroups(Add) & ~TrapRemove;
|
|
228 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) {
|
|
229 Arg->claim();
|
|
230 TrapRemove |= expandSanitizerGroups(parseArgValues(D, Arg, true));
|
|
231 }
|
|
232 }
|
|
233
|
|
234 // Apply default trapping behavior.
|
|
235 TrappingKinds |= TrappingDefault & ~TrapRemove;
|
|
236
|
|
237 return TrappingKinds;
|
|
238 }
|
|
239
|
|
240 bool SanitizerArgs::needsUbsanRt() const {
|
|
241 // All of these include ubsan.
|
|
242 if (needsAsanRt() || needsMsanRt() || needsHwasanRt() || needsTsanRt() ||
|
|
243 needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() ||
|
|
244 (needsScudoRt() && !requiresMinimalRuntime()))
|
|
245 return false;
|
|
246
|
|
247 return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) ||
|
|
248 CoverageFeatures;
|
|
249 }
|
|
250
|
|
251 bool SanitizerArgs::needsCfiRt() const {
|
|
252 return !(Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
|
|
253 CfiCrossDso && !ImplicitCfiRuntime;
|
|
254 }
|
|
255
|
|
256 bool SanitizerArgs::needsCfiDiagRt() const {
|
|
257 return (Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
|
|
258 CfiCrossDso && !ImplicitCfiRuntime;
|
|
259 }
|
|
260
|
|
261 bool SanitizerArgs::requiresPIE() const {
|
|
262 return NeedPIE || (Sanitizers.Mask & RequiresPIE);
|
|
263 }
|
|
264
|
|
265 bool SanitizerArgs::needsUnwindTables() const {
|
|
266 return static_cast<bool>(Sanitizers.Mask & NeedsUnwindTables);
|
|
267 }
|
|
268
|
|
269 bool SanitizerArgs::needsLTO() const {
|
|
270 return static_cast<bool>(Sanitizers.Mask & NeedsLTO);
|
|
271 }
|
|
272
|
|
273 SanitizerArgs::SanitizerArgs(const ToolChain &TC,
|
|
274 const llvm::opt::ArgList &Args) {
|
|
275 SanitizerMask AllRemove; // During the loop below, the accumulated set of
|
|
276 // sanitizers disabled by the current sanitizer
|
|
277 // argument or any argument after it.
|
|
278 SanitizerMask AllAddedKinds; // Mask of all sanitizers ever enabled by
|
|
279 // -fsanitize= flags (directly or via group
|
|
280 // expansion), some of which may be disabled
|
|
281 // later. Used to carefully prune
|
|
282 // unused-argument diagnostics.
|
|
283 SanitizerMask DiagnosedKinds; // All Kinds we have diagnosed up to now.
|
|
284 // Used to deduplicate diagnostics.
|
|
285 SanitizerMask Kinds;
|
|
286 const SanitizerMask Supported = setGroupBits(TC.getSupportedSanitizers());
|
|
287
|
|
288 CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
|
|
289 options::OPT_fno_sanitize_cfi_cross_dso, false);
|
|
290
|
|
291 ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
|
|
292
|
|
293 const Driver &D = TC.getDriver();
|
|
294 SanitizerMask TrappingKinds = parseSanitizeTrapArgs(D, Args);
|
|
295 SanitizerMask InvalidTrappingKinds = TrappingKinds & NotAllowedWithTrap;
|
|
296
|
|
297 MinimalRuntime =
|
|
298 Args.hasFlag(options::OPT_fsanitize_minimal_runtime,
|
|
299 options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime);
|
|
300
|
|
301 // The object size sanitizer should not be enabled at -O0.
|
|
302 Arg *OptLevel = Args.getLastArg(options::OPT_O_Group);
|
|
303 bool RemoveObjectSizeAtO0 =
|
|
304 !OptLevel || OptLevel->getOption().matches(options::OPT_O0);
|
|
305
|
|
306 for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
|
|
307 I != E; ++I) {
|
|
308 const auto *Arg = *I;
|
|
309 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
|
|
310 Arg->claim();
|
|
311 SanitizerMask Add = parseArgValues(D, Arg, /*AllowGroups=*/true);
|
|
312
|
|
313 if (RemoveObjectSizeAtO0) {
|
|
314 AllRemove |= SanitizerKind::ObjectSize;
|
|
315
|
|
316 // The user explicitly enabled the object size sanitizer. Warn
|
|
317 // that this does nothing at -O0.
|
|
318 if (Add & SanitizerKind::ObjectSize)
|
|
319 D.Diag(diag::warn_drv_object_size_disabled_O0)
|
|
320 << Arg->getAsString(Args);
|
|
321 }
|
|
322
|
|
323 AllAddedKinds |= expandSanitizerGroups(Add);
|
|
324
|
|
325 // Avoid diagnosing any sanitizer which is disabled later.
|
|
326 Add &= ~AllRemove;
|
|
327 // At this point we have not expanded groups, so any unsupported
|
|
328 // sanitizers in Add are those which have been explicitly enabled.
|
|
329 // Diagnose them.
|
|
330 if (SanitizerMask KindsToDiagnose =
|
|
331 Add & InvalidTrappingKinds & ~DiagnosedKinds) {
|
|
332 std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
|
|
333 D.Diag(diag::err_drv_argument_not_allowed_with)
|
|
334 << Desc << "-fsanitize-trap=undefined";
|
|
335 DiagnosedKinds |= KindsToDiagnose;
|
|
336 }
|
|
337 Add &= ~InvalidTrappingKinds;
|
|
338
|
|
339 if (MinimalRuntime) {
|
|
340 if (SanitizerMask KindsToDiagnose =
|
|
341 Add & NotAllowedWithMinimalRuntime & ~DiagnosedKinds) {
|
|
342 std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
|
|
343 D.Diag(diag::err_drv_argument_not_allowed_with)
|
|
344 << Desc << "-fsanitize-minimal-runtime";
|
|
345 DiagnosedKinds |= KindsToDiagnose;
|
|
346 }
|
|
347 Add &= ~NotAllowedWithMinimalRuntime;
|
|
348 }
|
|
349
|
|
350 // FIXME: Make CFI on member function calls compatible with cross-DSO CFI.
|
|
351 // There are currently two problems:
|
|
352 // - Virtual function call checks need to pass a pointer to the function
|
|
353 // address to llvm.type.test and a pointer to the address point to the
|
|
354 // diagnostic function. Currently we pass the same pointer to both
|
|
355 // places.
|
|
356 // - Non-virtual function call checks may need to check multiple type
|
|
357 // identifiers.
|
|
358 // Fixing both of those may require changes to the cross-DSO CFI
|
|
359 // interface.
|
|
360 if (CfiCrossDso && (Add & SanitizerKind::CFIMFCall & ~DiagnosedKinds)) {
|
|
361 D.Diag(diag::err_drv_argument_not_allowed_with)
|
|
362 << "-fsanitize=cfi-mfcall"
|
|
363 << "-fsanitize-cfi-cross-dso";
|
|
364 Add &= ~SanitizerKind::CFIMFCall;
|
|
365 DiagnosedKinds |= SanitizerKind::CFIMFCall;
|
|
366 }
|
|
367
|
|
368 if (SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
|
|
369 std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
|
|
370 D.Diag(diag::err_drv_unsupported_opt_for_target)
|
|
371 << Desc << TC.getTriple().str();
|
|
372 DiagnosedKinds |= KindsToDiagnose;
|
|
373 }
|
|
374 Add &= Supported;
|
|
375
|
|
376 // Test for -fno-rtti + explicit -fsanitizer=vptr before expanding groups
|
|
377 // so we don't error out if -fno-rtti and -fsanitize=undefined were
|
|
378 // passed.
|
|
379 if ((Add & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {
|
|
380 if (const llvm::opt::Arg *NoRTTIArg = TC.getRTTIArg()) {
|
|
381 assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) &&
|
|
382 "RTTI disabled without -fno-rtti option?");
|
|
383 // The user explicitly passed -fno-rtti with -fsanitize=vptr, but
|
|
384 // the vptr sanitizer requires RTTI, so this is a user error.
|
|
385 D.Diag(diag::err_drv_argument_not_allowed_with)
|
|
386 << "-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
|
|
387 } else {
|
|
388 // The vptr sanitizer requires RTTI, but RTTI is disabled (by
|
|
389 // default). Warn that the vptr sanitizer is being disabled.
|
|
390 D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
|
|
391 }
|
|
392
|
|
393 // Take out the Vptr sanitizer from the enabled sanitizers
|
|
394 AllRemove |= SanitizerKind::Vptr;
|
|
395 }
|
|
396
|
|
397 Add = expandSanitizerGroups(Add);
|
|
398 // Group expansion may have enabled a sanitizer which is disabled later.
|
|
399 Add &= ~AllRemove;
|
|
400 // Silently discard any unsupported sanitizers implicitly enabled through
|
|
401 // group expansion.
|
|
402 Add &= ~InvalidTrappingKinds;
|
|
403 if (MinimalRuntime) {
|
|
404 Add &= ~NotAllowedWithMinimalRuntime;
|
|
405 }
|
|
406 if (CfiCrossDso)
|
|
407 Add &= ~SanitizerKind::CFIMFCall;
|
|
408 Add &= Supported;
|
|
409
|
|
410 if (Add & SanitizerKind::Fuzzer)
|
|
411 Add |= SanitizerKind::FuzzerNoLink;
|
|
412
|
|
413 // Enable coverage if the fuzzing flag is set.
|
|
414 if (Add & SanitizerKind::FuzzerNoLink) {
|
|
415 CoverageFeatures |= CoverageInline8bitCounters | CoverageIndirCall |
|
|
416 CoverageTraceCmp | CoveragePCTable;
|
|
417 // Due to TLS differences, stack depth tracking is only enabled on Linux
|
|
418 if (TC.getTriple().isOSLinux())
|
|
419 CoverageFeatures |= CoverageStackDepth;
|
|
420 }
|
|
421
|
|
422 Kinds |= Add;
|
|
423 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
|
|
424 Arg->claim();
|
|
425 SanitizerMask Remove = parseArgValues(D, Arg, true);
|
|
426 AllRemove |= expandSanitizerGroups(Remove);
|
|
427 }
|
|
428 }
|
|
429
|
|
430 std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
|
|
431 std::make_pair(SanitizerKind::Address,
|
|
432 SanitizerKind::Thread | SanitizerKind::Memory),
|
|
433 std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory),
|
|
434 std::make_pair(SanitizerKind::Leak,
|
|
435 SanitizerKind::Thread | SanitizerKind::Memory),
|
|
436 std::make_pair(SanitizerKind::KernelAddress,
|
|
437 SanitizerKind::Address | SanitizerKind::Leak |
|
|
438 SanitizerKind::Thread | SanitizerKind::Memory),
|
|
439 std::make_pair(SanitizerKind::HWAddress,
|
|
440 SanitizerKind::Address | SanitizerKind::Thread |
|
|
441 SanitizerKind::Memory | SanitizerKind::KernelAddress),
|
|
442 std::make_pair(SanitizerKind::Scudo,
|
|
443 SanitizerKind::Address | SanitizerKind::HWAddress |
|
|
444 SanitizerKind::Leak | SanitizerKind::Thread |
|
|
445 SanitizerKind::Memory | SanitizerKind::KernelAddress),
|
|
446 std::make_pair(SanitizerKind::SafeStack,
|
|
447 (TC.getTriple().isOSFuchsia() ? SanitizerMask()
|
|
448 : SanitizerKind::Leak) |
|
|
449 SanitizerKind::Address | SanitizerKind::HWAddress |
|
|
450 SanitizerKind::Thread | SanitizerKind::Memory |
|
|
451 SanitizerKind::KernelAddress),
|
|
452 std::make_pair(SanitizerKind::KernelHWAddress,
|
|
453 SanitizerKind::Address | SanitizerKind::HWAddress |
|
|
454 SanitizerKind::Leak | SanitizerKind::Thread |
|
|
455 SanitizerKind::Memory | SanitizerKind::KernelAddress |
|
|
456 SanitizerKind::SafeStack),
|
|
457 std::make_pair(SanitizerKind::KernelMemory,
|
|
458 SanitizerKind::Address | SanitizerKind::HWAddress |
|
|
459 SanitizerKind::Leak | SanitizerKind::Thread |
|
|
460 SanitizerKind::Memory | SanitizerKind::KernelAddress |
|
|
461 SanitizerKind::Scudo | SanitizerKind::SafeStack),
|
|
462 std::make_pair(SanitizerKind::MemTag,
|
|
463 SanitizerKind::Address | SanitizerKind::KernelAddress |
|
|
464 SanitizerKind::HWAddress |
|
|
465 SanitizerKind::KernelHWAddress)};
|
|
466 // Enable toolchain specific default sanitizers if not explicitly disabled.
|
|
467 SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove;
|
|
468
|
|
469 // Disable default sanitizers that are incompatible with explicitly requested
|
|
470 // ones.
|
|
471 for (auto G : IncompatibleGroups) {
|
|
472 SanitizerMask Group = G.first;
|
|
473 if ((Default & Group) && (Kinds & G.second))
|
|
474 Default &= ~Group;
|
|
475 }
|
|
476
|
|
477 Kinds |= Default;
|
|
478
|
|
479 // We disable the vptr sanitizer if it was enabled by group expansion but RTTI
|
|
480 // is disabled.
|
|
481 if ((Kinds & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {
|
|
482 Kinds &= ~SanitizerKind::Vptr;
|
|
483 }
|
|
484
|
|
485 // Check that LTO is enabled if we need it.
|
|
486 if ((Kinds & NeedsLTO) && !D.isUsingLTO()) {
|
|
487 D.Diag(diag::err_drv_argument_only_allowed_with)
|
|
488 << lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto";
|
|
489 }
|
|
490
|
|
491 if ((Kinds & SanitizerKind::ShadowCallStack) &&
|
|
492 TC.getTriple().getArch() == llvm::Triple::aarch64 &&
|
|
493 !llvm::AArch64::isX18ReservedByDefault(TC.getTriple()) &&
|
|
494 !Args.hasArg(options::OPT_ffixed_x18)) {
|
|
495 D.Diag(diag::err_drv_argument_only_allowed_with)
|
|
496 << lastArgumentForMask(D, Args, Kinds & SanitizerKind::ShadowCallStack)
|
|
497 << "-ffixed-x18";
|
|
498 }
|
|
499
|
|
500 // Report error if there are non-trapping sanitizers that require
|
|
501 // c++abi-specific parts of UBSan runtime, and they are not provided by the
|
|
502 // toolchain. We don't have a good way to check the latter, so we just
|
|
503 // check if the toolchan supports vptr.
|
|
504 if (~Supported & SanitizerKind::Vptr) {
|
|
505 SanitizerMask KindsToDiagnose = Kinds & ~TrappingKinds & NeedsUbsanCxxRt;
|
|
506 // The runtime library supports the Microsoft C++ ABI, but only well enough
|
|
507 // for CFI. FIXME: Remove this once we support vptr on Windows.
|
|
508 if (TC.getTriple().isOSWindows())
|
|
509 KindsToDiagnose &= ~SanitizerKind::CFI;
|
|
510 if (KindsToDiagnose) {
|
|
511 SanitizerSet S;
|
|
512 S.Mask = KindsToDiagnose;
|
|
513 D.Diag(diag::err_drv_unsupported_opt_for_target)
|
|
514 << ("-fno-sanitize-trap=" + toString(S)) << TC.getTriple().str();
|
|
515 Kinds &= ~KindsToDiagnose;
|
|
516 }
|
|
517 }
|
|
518
|
|
519 // Warn about incompatible groups of sanitizers.
|
|
520 for (auto G : IncompatibleGroups) {
|
|
521 SanitizerMask Group = G.first;
|
|
522 if (Kinds & Group) {
|
|
523 if (SanitizerMask Incompatible = Kinds & G.second) {
|
|
524 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
|
|
525 << lastArgumentForMask(D, Args, Group)
|
|
526 << lastArgumentForMask(D, Args, Incompatible);
|
|
527 Kinds &= ~Incompatible;
|
|
528 }
|
|
529 }
|
|
530 }
|
|
531 // FIXME: Currently -fsanitize=leak is silently ignored in the presence of
|
|
532 // -fsanitize=address. Perhaps it should print an error, or perhaps
|
|
533 // -f(-no)sanitize=leak should change whether leak detection is enabled by
|
|
534 // default in ASan?
|
|
535
|
|
536 // Parse -f(no-)?sanitize-recover flags.
|
|
537 SanitizerMask RecoverableKinds = RecoverableByDefault | AlwaysRecoverable;
|
|
538 SanitizerMask DiagnosedUnrecoverableKinds;
|
|
539 SanitizerMask DiagnosedAlwaysRecoverableKinds;
|
|
540 for (const auto *Arg : Args) {
|
173
|
541 if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
|
150
|
542 SanitizerMask Add = parseArgValues(D, Arg, true);
|
|
543 // Report error if user explicitly tries to recover from unrecoverable
|
|
544 // sanitizer.
|
|
545 if (SanitizerMask KindsToDiagnose =
|
|
546 Add & Unrecoverable & ~DiagnosedUnrecoverableKinds) {
|
|
547 SanitizerSet SetToDiagnose;
|
|
548 SetToDiagnose.Mask |= KindsToDiagnose;
|
|
549 D.Diag(diag::err_drv_unsupported_option_argument)
|
|
550 << Arg->getOption().getName() << toString(SetToDiagnose);
|
|
551 DiagnosedUnrecoverableKinds |= KindsToDiagnose;
|
|
552 }
|
|
553 RecoverableKinds |= expandSanitizerGroups(Add);
|
|
554 Arg->claim();
|
|
555 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {
|
|
556 SanitizerMask Remove = parseArgValues(D, Arg, true);
|
|
557 // Report error if user explicitly tries to disable recovery from
|
|
558 // always recoverable sanitizer.
|
|
559 if (SanitizerMask KindsToDiagnose =
|
|
560 Remove & AlwaysRecoverable & ~DiagnosedAlwaysRecoverableKinds) {
|
|
561 SanitizerSet SetToDiagnose;
|
|
562 SetToDiagnose.Mask |= KindsToDiagnose;
|
|
563 D.Diag(diag::err_drv_unsupported_option_argument)
|
|
564 << Arg->getOption().getName() << toString(SetToDiagnose);
|
|
565 DiagnosedAlwaysRecoverableKinds |= KindsToDiagnose;
|
|
566 }
|
|
567 RecoverableKinds &= ~expandSanitizerGroups(Remove);
|
|
568 Arg->claim();
|
|
569 }
|
|
570 }
|
|
571 RecoverableKinds &= Kinds;
|
|
572 RecoverableKinds &= ~Unrecoverable;
|
|
573
|
|
574 TrappingKinds &= Kinds;
|
|
575 RecoverableKinds &= ~TrappingKinds;
|
|
576
|
|
577 // Setup blacklist files.
|
173
|
578 // Add default blacklist from resource directory for activated sanitizers, and
|
|
579 // validate special case lists format.
|
|
580 if (!Args.hasArgNoClaim(options::OPT_fno_sanitize_blacklist))
|
|
581 addDefaultBlacklists(D, Kinds, SystemBlacklistFiles);
|
|
582
|
|
583 // Parse -f(no-)?sanitize-blacklist options.
|
|
584 // This also validates special case lists format.
|
|
585 parseSpecialCaseListArg(D, Args, UserBlacklistFiles,
|
|
586 options::OPT_fsanitize_blacklist,
|
|
587 options::OPT_fno_sanitize_blacklist,
|
|
588 clang::diag::err_drv_malformed_sanitizer_blacklist);
|
150
|
589
|
|
590 // Parse -f[no-]sanitize-memory-track-origins[=level] options.
|
|
591 if (AllAddedKinds & SanitizerKind::Memory) {
|
|
592 if (Arg *A =
|
|
593 Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
|
|
594 options::OPT_fsanitize_memory_track_origins,
|
|
595 options::OPT_fno_sanitize_memory_track_origins)) {
|
|
596 if (A->getOption().matches(options::OPT_fsanitize_memory_track_origins)) {
|
|
597 MsanTrackOrigins = 2;
|
|
598 } else if (A->getOption().matches(
|
|
599 options::OPT_fno_sanitize_memory_track_origins)) {
|
|
600 MsanTrackOrigins = 0;
|
|
601 } else {
|
|
602 StringRef S = A->getValue();
|
|
603 if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
|
|
604 MsanTrackOrigins > 2) {
|
|
605 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
|
|
606 }
|
|
607 }
|
|
608 }
|
|
609 MsanUseAfterDtor =
|
|
610 Args.hasFlag(options::OPT_fsanitize_memory_use_after_dtor,
|
|
611 options::OPT_fno_sanitize_memory_use_after_dtor,
|
|
612 MsanUseAfterDtor);
|
|
613 NeedPIE |= !(TC.getTriple().isOSLinux() &&
|
|
614 TC.getTriple().getArch() == llvm::Triple::x86_64);
|
|
615 } else {
|
|
616 MsanUseAfterDtor = false;
|
|
617 }
|
|
618
|
|
619 if (AllAddedKinds & SanitizerKind::Thread) {
|
|
620 TsanMemoryAccess = Args.hasFlag(
|
|
621 options::OPT_fsanitize_thread_memory_access,
|
|
622 options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess);
|
|
623 TsanFuncEntryExit = Args.hasFlag(
|
|
624 options::OPT_fsanitize_thread_func_entry_exit,
|
|
625 options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit);
|
|
626 TsanAtomics =
|
|
627 Args.hasFlag(options::OPT_fsanitize_thread_atomics,
|
|
628 options::OPT_fno_sanitize_thread_atomics, TsanAtomics);
|
|
629 }
|
|
630
|
|
631 if (AllAddedKinds & SanitizerKind::CFI) {
|
|
632 // Without PIE, external function address may resolve to a PLT record, which
|
|
633 // can not be verified by the target module.
|
|
634 NeedPIE |= CfiCrossDso;
|
|
635 CfiICallGeneralizePointers =
|
|
636 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
|
|
637
|
|
638 if (CfiCrossDso && CfiICallGeneralizePointers)
|
|
639 D.Diag(diag::err_drv_argument_not_allowed_with)
|
|
640 << "-fsanitize-cfi-cross-dso"
|
|
641 << "-fsanitize-cfi-icall-generalize-pointers";
|
|
642
|
|
643 CfiCanonicalJumpTables =
|
|
644 Args.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables,
|
|
645 options::OPT_fno_sanitize_cfi_canonical_jump_tables, true);
|
|
646 }
|
|
647
|
|
648 Stats = Args.hasFlag(options::OPT_fsanitize_stats,
|
|
649 options::OPT_fno_sanitize_stats, false);
|
|
650
|
|
651 if (MinimalRuntime) {
|
|
652 SanitizerMask IncompatibleMask =
|
|
653 Kinds & ~setGroupBits(CompatibleWithMinimalRuntime);
|
|
654 if (IncompatibleMask)
|
|
655 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
|
|
656 << "-fsanitize-minimal-runtime"
|
|
657 << lastArgumentForMask(D, Args, IncompatibleMask);
|
|
658
|
|
659 SanitizerMask NonTrappingCfi = Kinds & SanitizerKind::CFI & ~TrappingKinds;
|
|
660 if (NonTrappingCfi)
|
|
661 D.Diag(clang::diag::err_drv_argument_only_allowed_with)
|
|
662 << "fsanitize-minimal-runtime"
|
|
663 << "fsanitize-trap=cfi";
|
|
664 }
|
|
665
|
|
666 // Parse -f(no-)?sanitize-coverage flags if coverage is supported by the
|
|
667 // enabled sanitizers.
|
|
668 for (const auto *Arg : Args) {
|
|
669 if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
|
|
670 int LegacySanitizeCoverage;
|
|
671 if (Arg->getNumValues() == 1 &&
|
|
672 !StringRef(Arg->getValue(0))
|
|
673 .getAsInteger(0, LegacySanitizeCoverage)) {
|
|
674 CoverageFeatures = 0;
|
|
675 Arg->claim();
|
|
676 if (LegacySanitizeCoverage != 0) {
|
|
677 D.Diag(diag::warn_drv_deprecated_arg)
|
|
678 << Arg->getAsString(Args) << "-fsanitize-coverage=trace-pc-guard";
|
|
679 }
|
|
680 continue;
|
|
681 }
|
|
682 CoverageFeatures |= parseCoverageFeatures(D, Arg);
|
|
683
|
|
684 // Disable coverage and not claim the flags if there is at least one
|
|
685 // non-supporting sanitizer.
|
|
686 if (!(AllAddedKinds & ~AllRemove & ~setGroupBits(SupportsCoverage))) {
|
|
687 Arg->claim();
|
|
688 } else {
|
|
689 CoverageFeatures = 0;
|
|
690 }
|
|
691 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
|
|
692 Arg->claim();
|
|
693 CoverageFeatures &= ~parseCoverageFeatures(D, Arg);
|
|
694 }
|
|
695 }
|
|
696 // Choose at most one coverage type: function, bb, or edge.
|
|
697 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageBB))
|
|
698 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
|
|
699 << "-fsanitize-coverage=func"
|
|
700 << "-fsanitize-coverage=bb";
|
|
701 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageEdge))
|
|
702 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
|
|
703 << "-fsanitize-coverage=func"
|
|
704 << "-fsanitize-coverage=edge";
|
|
705 if ((CoverageFeatures & CoverageBB) && (CoverageFeatures & CoverageEdge))
|
|
706 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
|
|
707 << "-fsanitize-coverage=bb"
|
|
708 << "-fsanitize-coverage=edge";
|
|
709 // Basic block tracing and 8-bit counters require some type of coverage
|
|
710 // enabled.
|
|
711 if (CoverageFeatures & CoverageTraceBB)
|
|
712 D.Diag(clang::diag::warn_drv_deprecated_arg)
|
|
713 << "-fsanitize-coverage=trace-bb"
|
|
714 << "-fsanitize-coverage=trace-pc-guard";
|
|
715 if (CoverageFeatures & Coverage8bitCounters)
|
|
716 D.Diag(clang::diag::warn_drv_deprecated_arg)
|
|
717 << "-fsanitize-coverage=8bit-counters"
|
|
718 << "-fsanitize-coverage=trace-pc-guard";
|
|
719
|
|
720 int InsertionPointTypes = CoverageFunc | CoverageBB | CoverageEdge;
|
173
|
721 int InstrumentationTypes = CoverageTracePC | CoverageTracePCGuard |
|
|
722 CoverageInline8bitCounters |
|
|
723 CoverageInlineBoolFlag;
|
150
|
724 if ((CoverageFeatures & InsertionPointTypes) &&
|
|
725 !(CoverageFeatures & InstrumentationTypes)) {
|
|
726 D.Diag(clang::diag::warn_drv_deprecated_arg)
|
|
727 << "-fsanitize-coverage=[func|bb|edge]"
|
|
728 << "-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc]";
|
|
729 }
|
|
730
|
|
731 // trace-pc w/o func/bb/edge implies edge.
|
|
732 if (!(CoverageFeatures & InsertionPointTypes)) {
|
|
733 if (CoverageFeatures &
|
173
|
734 (CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters |
|
|
735 CoverageInlineBoolFlag))
|
150
|
736 CoverageFeatures |= CoverageEdge;
|
|
737
|
|
738 if (CoverageFeatures & CoverageStackDepth)
|
|
739 CoverageFeatures |= CoverageFunc;
|
|
740 }
|
|
741
|
173
|
742 // Parse -fsanitize-coverage-(black|white)list options if coverage enabled.
|
|
743 // This also validates special case lists format.
|
|
744 // Here, OptSpecifier() acts as a never-matching command-line argument.
|
|
745 // So, there is no way to clear coverage lists but you can append to them.
|
|
746 if (CoverageFeatures) {
|
|
747 parseSpecialCaseListArg(
|
|
748 D, Args, CoverageWhitelistFiles,
|
|
749 options::OPT_fsanitize_coverage_whitelist, OptSpecifier(),
|
|
750 clang::diag::err_drv_malformed_sanitizer_coverage_whitelist);
|
|
751 parseSpecialCaseListArg(
|
|
752 D, Args, CoverageBlacklistFiles,
|
|
753 options::OPT_fsanitize_coverage_blacklist, OptSpecifier(),
|
|
754 clang::diag::err_drv_malformed_sanitizer_coverage_blacklist);
|
|
755 }
|
|
756
|
150
|
757 SharedRuntime =
|
|
758 Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan,
|
|
759 TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() ||
|
|
760 TC.getTriple().isOSDarwin());
|
|
761
|
|
762 ImplicitCfiRuntime = TC.getTriple().isAndroid();
|
|
763
|
|
764 if (AllAddedKinds & SanitizerKind::Address) {
|
|
765 NeedPIE |= TC.getTriple().isOSFuchsia();
|
|
766 if (Arg *A =
|
|
767 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
|
|
768 StringRef S = A->getValue();
|
|
769 // Legal values are 0 and 1, 2, but in future we may add more levels.
|
|
770 if (S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
|
|
771 AsanFieldPadding > 2) {
|
|
772 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
|
|
773 }
|
|
774 }
|
|
775
|
|
776 if (Arg *WindowsDebugRTArg =
|
|
777 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
|
|
778 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
|
|
779 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
|
|
780 switch (WindowsDebugRTArg->getOption().getID()) {
|
|
781 case options::OPT__SLASH_MTd:
|
|
782 case options::OPT__SLASH_MDd:
|
|
783 case options::OPT__SLASH_LDd:
|
|
784 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
|
|
785 << WindowsDebugRTArg->getAsString(Args)
|
|
786 << lastArgumentForMask(D, Args, SanitizerKind::Address);
|
|
787 D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
|
|
788 }
|
|
789 }
|
|
790
|
|
791 AsanUseAfterScope = Args.hasFlag(
|
|
792 options::OPT_fsanitize_address_use_after_scope,
|
|
793 options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);
|
|
794
|
|
795 AsanPoisonCustomArrayCookie = Args.hasFlag(
|
|
796 options::OPT_fsanitize_address_poison_custom_array_cookie,
|
|
797 options::OPT_fno_sanitize_address_poison_custom_array_cookie,
|
|
798 AsanPoisonCustomArrayCookie);
|
|
799
|
|
800 // As a workaround for a bug in gold 2.26 and earlier, dead stripping of
|
|
801 // globals in ASan is disabled by default on ELF targets.
|
|
802 // See https://sourceware.org/bugzilla/show_bug.cgi?id=19002
|
|
803 AsanGlobalsDeadStripping =
|
|
804 !TC.getTriple().isOSBinFormatELF() || TC.getTriple().isOSFuchsia() ||
|
|
805 TC.getTriple().isPS4() ||
|
|
806 Args.hasArg(options::OPT_fsanitize_address_globals_dead_stripping);
|
|
807
|
|
808 AsanUseOdrIndicator =
|
|
809 Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
|
|
810 options::OPT_fno_sanitize_address_use_odr_indicator,
|
|
811 AsanUseOdrIndicator);
|
|
812
|
|
813 if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) {
|
|
814 AsanInvalidPointerCmp = true;
|
|
815 }
|
|
816
|
|
817 if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) {
|
|
818 AsanInvalidPointerSub = true;
|
|
819 }
|
|
820
|
|
821 } else {
|
|
822 AsanUseAfterScope = false;
|
|
823 // -fsanitize=pointer-compare/pointer-subtract requires -fsanitize=address.
|
|
824 SanitizerMask DetectInvalidPointerPairs =
|
|
825 SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract;
|
|
826 if (AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) {
|
|
827 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)
|
|
828 << lastArgumentForMask(D, Args,
|
|
829 SanitizerKind::PointerCompare |
|
|
830 SanitizerKind::PointerSubtract)
|
|
831 << "-fsanitize=address";
|
|
832 }
|
|
833 }
|
|
834
|
|
835 if (AllAddedKinds & SanitizerKind::HWAddress) {
|
|
836 if (Arg *HwasanAbiArg =
|
|
837 Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {
|
|
838 HwasanAbi = HwasanAbiArg->getValue();
|
|
839 if (HwasanAbi != "platform" && HwasanAbi != "interceptor")
|
|
840 D.Diag(clang::diag::err_drv_invalid_value)
|
|
841 << HwasanAbiArg->getAsString(Args) << HwasanAbi;
|
|
842 } else {
|
|
843 HwasanAbi = "interceptor";
|
|
844 }
|
|
845 }
|
|
846
|
|
847 if (AllAddedKinds & SanitizerKind::SafeStack) {
|
|
848 // SafeStack runtime is built into the system on Android and Fuchsia.
|
|
849 SafeStackRuntime =
|
|
850 !TC.getTriple().isAndroid() && !TC.getTriple().isOSFuchsia();
|
|
851 }
|
|
852
|
|
853 LinkRuntimes =
|
|
854 Args.hasFlag(options::OPT_fsanitize_link_runtime,
|
|
855 options::OPT_fno_sanitize_link_runtime, LinkRuntimes);
|
|
856
|
|
857 // Parse -link-cxx-sanitizer flag.
|
|
858 LinkCXXRuntimes = Args.hasArg(options::OPT_fsanitize_link_cxx_runtime,
|
|
859 options::OPT_fno_sanitize_link_cxx_runtime,
|
|
860 LinkCXXRuntimes) ||
|
|
861 D.CCCIsCXX();
|
|
862
|
|
863 // Finally, initialize the set of available and recoverable sanitizers.
|
|
864 Sanitizers.Mask |= Kinds;
|
|
865 RecoverableSanitizers.Mask |= RecoverableKinds;
|
|
866 TrapSanitizers.Mask |= TrappingKinds;
|
|
867 assert(!(RecoverableKinds & TrappingKinds) &&
|
|
868 "Overlap between recoverable and trapping sanitizers");
|
|
869 }
|
|
870
|
|
871 static std::string toString(const clang::SanitizerSet &Sanitizers) {
|
|
872 std::string Res;
|
|
873 #define SANITIZER(NAME, ID) \
|
|
874 if (Sanitizers.has(SanitizerKind::ID)) { \
|
|
875 if (!Res.empty()) \
|
|
876 Res += ","; \
|
|
877 Res += NAME; \
|
|
878 }
|
|
879 #include "clang/Basic/Sanitizers.def"
|
|
880 return Res;
|
|
881 }
|
|
882
|
173
|
883 static void addSpecialCaseListOpt(const llvm::opt::ArgList &Args,
|
|
884 llvm::opt::ArgStringList &CmdArgs,
|
|
885 const char *SCLOptFlag,
|
|
886 const std::vector<std::string> &SCLFiles) {
|
|
887 for (const auto &SCLPath : SCLFiles) {
|
|
888 SmallString<64> SCLOpt(SCLOptFlag);
|
|
889 SCLOpt += SCLPath;
|
|
890 CmdArgs.push_back(Args.MakeArgString(SCLOpt));
|
|
891 }
|
|
892 }
|
|
893
|
150
|
894 static void addIncludeLinkerOption(const ToolChain &TC,
|
|
895 const llvm::opt::ArgList &Args,
|
|
896 llvm::opt::ArgStringList &CmdArgs,
|
|
897 StringRef SymbolName) {
|
|
898 SmallString<64> LinkerOptionFlag;
|
|
899 LinkerOptionFlag = "--linker-option=/include:";
|
|
900 if (TC.getTriple().getArch() == llvm::Triple::x86) {
|
|
901 // Win32 mangles C function names with a '_' prefix.
|
|
902 LinkerOptionFlag += '_';
|
|
903 }
|
|
904 LinkerOptionFlag += SymbolName;
|
|
905 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
|
|
906 }
|
|
907
|
|
908 static bool hasTargetFeatureMTE(const llvm::opt::ArgStringList &CmdArgs) {
|
|
909 for (auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End; ++Start) {
|
|
910 auto It = std::find(Start, End, StringRef("+mte"));
|
|
911 if (It == End)
|
|
912 break;
|
|
913 if (It > Start && *std::prev(It) == StringRef("-target-feature"))
|
|
914 return true;
|
|
915 Start = It;
|
|
916 }
|
|
917 return false;
|
|
918 }
|
|
919
|
|
920 void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
|
|
921 llvm::opt::ArgStringList &CmdArgs,
|
|
922 types::ID InputType) const {
|
|
923 // NVPTX doesn't currently support sanitizers. Bailing out here means that
|
|
924 // e.g. -fsanitize=address applies only to host code, which is what we want
|
|
925 // for now.
|
|
926 if (TC.getTriple().isNVPTX())
|
|
927 return;
|
|
928
|
|
929 // Translate available CoverageFeatures to corresponding clang-cc1 flags.
|
|
930 // Do it even if Sanitizers.empty() since some forms of coverage don't require
|
|
931 // sanitizers.
|
|
932 std::pair<int, const char *> CoverageFlags[] = {
|
173
|
933 std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"),
|
|
934 std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"),
|
|
935 std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"),
|
|
936 std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"),
|
|
937 std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"),
|
|
938 std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"),
|
|
939 std::make_pair(CoverageTraceDiv, "-fsanitize-coverage-trace-div"),
|
|
940 std::make_pair(CoverageTraceGep, "-fsanitize-coverage-trace-gep"),
|
|
941 std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"),
|
|
942 std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"),
|
|
943 std::make_pair(CoverageTracePCGuard,
|
|
944 "-fsanitize-coverage-trace-pc-guard"),
|
|
945 std::make_pair(CoverageInline8bitCounters,
|
|
946 "-fsanitize-coverage-inline-8bit-counters"),
|
|
947 std::make_pair(CoverageInlineBoolFlag,
|
|
948 "-fsanitize-coverage-inline-bool-flag"),
|
|
949 std::make_pair(CoveragePCTable, "-fsanitize-coverage-pc-table"),
|
|
950 std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune"),
|
|
951 std::make_pair(CoverageStackDepth, "-fsanitize-coverage-stack-depth")};
|
150
|
952 for (auto F : CoverageFlags) {
|
|
953 if (CoverageFeatures & F.first)
|
|
954 CmdArgs.push_back(F.second);
|
|
955 }
|
173
|
956 addSpecialCaseListOpt(
|
|
957 Args, CmdArgs, "-fsanitize-coverage-whitelist=", CoverageWhitelistFiles);
|
|
958 addSpecialCaseListOpt(
|
|
959 Args, CmdArgs, "-fsanitize-coverage-blacklist=", CoverageBlacklistFiles);
|
150
|
960
|
|
961 if (TC.getTriple().isOSWindows() && needsUbsanRt()) {
|
|
962 // Instruct the code generator to embed linker directives in the object file
|
|
963 // that cause the required runtime libraries to be linked.
|
173
|
964 CmdArgs.push_back(
|
|
965 Args.MakeArgString("--dependent-lib=" +
|
|
966 TC.getCompilerRTBasename(Args, "ubsan_standalone")));
|
150
|
967 if (types::isCXX(InputType))
|
|
968 CmdArgs.push_back(Args.MakeArgString(
|
173
|
969 "--dependent-lib=" +
|
|
970 TC.getCompilerRTBasename(Args, "ubsan_standalone_cxx")));
|
150
|
971 }
|
|
972 if (TC.getTriple().isOSWindows() && needsStatsRt()) {
|
173
|
973 CmdArgs.push_back(Args.MakeArgString(
|
|
974 "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats_client")));
|
150
|
975
|
|
976 // The main executable must export the stats runtime.
|
|
977 // FIXME: Only exporting from the main executable (e.g. based on whether the
|
|
978 // translation unit defines main()) would save a little space, but having
|
|
979 // multiple copies of the runtime shouldn't hurt.
|
173
|
980 CmdArgs.push_back(Args.MakeArgString(
|
|
981 "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats")));
|
150
|
982 addIncludeLinkerOption(TC, Args, CmdArgs, "__sanitizer_stats_register");
|
|
983 }
|
|
984
|
|
985 if (Sanitizers.empty())
|
|
986 return;
|
|
987 CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers)));
|
|
988
|
|
989 if (!RecoverableSanitizers.empty())
|
|
990 CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" +
|
|
991 toString(RecoverableSanitizers)));
|
|
992
|
|
993 if (!TrapSanitizers.empty())
|
|
994 CmdArgs.push_back(
|
|
995 Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));
|
|
996
|
173
|
997 addSpecialCaseListOpt(Args, CmdArgs,
|
|
998 "-fsanitize-blacklist=", UserBlacklistFiles);
|
|
999 addSpecialCaseListOpt(Args, CmdArgs,
|
|
1000 "-fsanitize-system-blacklist=", SystemBlacklistFiles);
|
150
|
1001
|
|
1002 if (MsanTrackOrigins)
|
|
1003 CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" +
|
|
1004 Twine(MsanTrackOrigins)));
|
|
1005
|
|
1006 if (MsanUseAfterDtor)
|
|
1007 CmdArgs.push_back("-fsanitize-memory-use-after-dtor");
|
|
1008
|
|
1009 // FIXME: Pass these parameters as function attributes, not as -llvm flags.
|
|
1010 if (!TsanMemoryAccess) {
|
|
1011 CmdArgs.push_back("-mllvm");
|
|
1012 CmdArgs.push_back("-tsan-instrument-memory-accesses=0");
|
|
1013 CmdArgs.push_back("-mllvm");
|
|
1014 CmdArgs.push_back("-tsan-instrument-memintrinsics=0");
|
|
1015 }
|
|
1016 if (!TsanFuncEntryExit) {
|
|
1017 CmdArgs.push_back("-mllvm");
|
|
1018 CmdArgs.push_back("-tsan-instrument-func-entry-exit=0");
|
|
1019 }
|
|
1020 if (!TsanAtomics) {
|
|
1021 CmdArgs.push_back("-mllvm");
|
|
1022 CmdArgs.push_back("-tsan-instrument-atomics=0");
|
|
1023 }
|
|
1024
|
|
1025 if (CfiCrossDso)
|
|
1026 CmdArgs.push_back("-fsanitize-cfi-cross-dso");
|
|
1027
|
|
1028 if (CfiICallGeneralizePointers)
|
|
1029 CmdArgs.push_back("-fsanitize-cfi-icall-generalize-pointers");
|
|
1030
|
|
1031 if (CfiCanonicalJumpTables)
|
|
1032 CmdArgs.push_back("-fsanitize-cfi-canonical-jump-tables");
|
|
1033
|
|
1034 if (Stats)
|
|
1035 CmdArgs.push_back("-fsanitize-stats");
|
|
1036
|
|
1037 if (MinimalRuntime)
|
|
1038 CmdArgs.push_back("-fsanitize-minimal-runtime");
|
|
1039
|
|
1040 if (AsanFieldPadding)
|
|
1041 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" +
|
|
1042 Twine(AsanFieldPadding)));
|
|
1043
|
|
1044 if (AsanUseAfterScope)
|
|
1045 CmdArgs.push_back("-fsanitize-address-use-after-scope");
|
|
1046
|
|
1047 if (AsanPoisonCustomArrayCookie)
|
|
1048 CmdArgs.push_back("-fsanitize-address-poison-custom-array-cookie");
|
|
1049
|
|
1050 if (AsanGlobalsDeadStripping)
|
|
1051 CmdArgs.push_back("-fsanitize-address-globals-dead-stripping");
|
|
1052
|
|
1053 if (AsanUseOdrIndicator)
|
|
1054 CmdArgs.push_back("-fsanitize-address-use-odr-indicator");
|
|
1055
|
|
1056 if (AsanInvalidPointerCmp) {
|
|
1057 CmdArgs.push_back("-mllvm");
|
|
1058 CmdArgs.push_back("-asan-detect-invalid-pointer-cmp");
|
|
1059 }
|
|
1060
|
|
1061 if (AsanInvalidPointerSub) {
|
|
1062 CmdArgs.push_back("-mllvm");
|
|
1063 CmdArgs.push_back("-asan-detect-invalid-pointer-sub");
|
|
1064 }
|
|
1065
|
|
1066 if (!HwasanAbi.empty()) {
|
|
1067 CmdArgs.push_back("-default-function-attr");
|
|
1068 CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi));
|
|
1069 }
|
|
1070
|
|
1071 if (Sanitizers.has(SanitizerKind::HWAddress)) {
|
|
1072 CmdArgs.push_back("-target-feature");
|
|
1073 CmdArgs.push_back("+tagged-globals");
|
|
1074 }
|
|
1075
|
|
1076 // MSan: Workaround for PR16386.
|
|
1077 // ASan: This is mainly to help LSan with cases such as
|
|
1078 // https://github.com/google/sanitizers/issues/373
|
|
1079 // We can't make this conditional on -fsanitize=leak, as that flag shouldn't
|
|
1080 // affect compilation.
|
|
1081 if (Sanitizers.has(SanitizerKind::Memory) ||
|
|
1082 Sanitizers.has(SanitizerKind::Address))
|
|
1083 CmdArgs.push_back("-fno-assume-sane-operator-new");
|
|
1084
|
|
1085 // Require -fvisibility= flag on non-Windows when compiling if vptr CFI is
|
|
1086 // enabled.
|
|
1087 if (Sanitizers.hasOneOf(CFIClasses) && !TC.getTriple().isOSWindows() &&
|
|
1088 !Args.hasArg(options::OPT_fvisibility_EQ)) {
|
|
1089 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)
|
|
1090 << lastArgumentForMask(TC.getDriver(), Args,
|
|
1091 Sanitizers.Mask & CFIClasses)
|
|
1092 << "-fvisibility=";
|
|
1093 }
|
|
1094
|
|
1095 if (Sanitizers.has(SanitizerKind::MemTag) && !hasTargetFeatureMTE(CmdArgs))
|
|
1096 TC.getDriver().Diag(diag::err_stack_tagging_requires_hardware_feature);
|
|
1097 }
|
|
1098
|
|
1099 SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
|
|
1100 bool DiagnoseErrors) {
|
|
1101 assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
|
|
1102 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
|
|
1103 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
|
|
1104 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
|
|
1105 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
|
|
1106 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) &&
|
|
1107 "Invalid argument in parseArgValues!");
|
|
1108 SanitizerMask Kinds;
|
|
1109 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
|
|
1110 const char *Value = A->getValue(i);
|
|
1111 SanitizerMask Kind;
|
|
1112 // Special case: don't accept -fsanitize=all.
|
|
1113 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
|
|
1114 0 == strcmp("all", Value))
|
|
1115 Kind = SanitizerMask();
|
|
1116 else
|
|
1117 Kind = parseSanitizerValue(Value, /*AllowGroups=*/true);
|
|
1118
|
|
1119 if (Kind)
|
|
1120 Kinds |= Kind;
|
|
1121 else if (DiagnoseErrors)
|
|
1122 D.Diag(clang::diag::err_drv_unsupported_option_argument)
|
|
1123 << A->getOption().getName() << Value;
|
|
1124 }
|
|
1125 return Kinds;
|
|
1126 }
|
|
1127
|
|
1128 int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A) {
|
|
1129 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
|
|
1130 A->getOption().matches(options::OPT_fno_sanitize_coverage));
|
|
1131 int Features = 0;
|
|
1132 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
|
|
1133 const char *Value = A->getValue(i);
|
|
1134 int F = llvm::StringSwitch<int>(Value)
|
173
|
1135 .Case("func", CoverageFunc)
|
|
1136 .Case("bb", CoverageBB)
|
|
1137 .Case("edge", CoverageEdge)
|
|
1138 .Case("indirect-calls", CoverageIndirCall)
|
|
1139 .Case("trace-bb", CoverageTraceBB)
|
|
1140 .Case("trace-cmp", CoverageTraceCmp)
|
|
1141 .Case("trace-div", CoverageTraceDiv)
|
|
1142 .Case("trace-gep", CoverageTraceGep)
|
|
1143 .Case("8bit-counters", Coverage8bitCounters)
|
|
1144 .Case("trace-pc", CoverageTracePC)
|
|
1145 .Case("trace-pc-guard", CoverageTracePCGuard)
|
|
1146 .Case("no-prune", CoverageNoPrune)
|
|
1147 .Case("inline-8bit-counters", CoverageInline8bitCounters)
|
|
1148 .Case("inline-bool-flag", CoverageInlineBoolFlag)
|
|
1149 .Case("pc-table", CoveragePCTable)
|
|
1150 .Case("stack-depth", CoverageStackDepth)
|
|
1151 .Default(0);
|
150
|
1152 if (F == 0)
|
|
1153 D.Diag(clang::diag::err_drv_unsupported_option_argument)
|
|
1154 << A->getOption().getName() << Value;
|
|
1155 Features |= F;
|
|
1156 }
|
|
1157 return Features;
|
|
1158 }
|
|
1159
|
|
1160 std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,
|
|
1161 SanitizerMask Mask) {
|
|
1162 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
|
|
1163 E = Args.rend();
|
|
1164 I != E; ++I) {
|
|
1165 const auto *Arg = *I;
|
|
1166 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
|
|
1167 SanitizerMask AddKinds =
|
|
1168 expandSanitizerGroups(parseArgValues(D, Arg, false));
|
|
1169 if (AddKinds & Mask)
|
|
1170 return describeSanitizeArg(Arg, Mask);
|
|
1171 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
|
|
1172 SanitizerMask RemoveKinds =
|
|
1173 expandSanitizerGroups(parseArgValues(D, Arg, false));
|
|
1174 Mask &= ~RemoveKinds;
|
|
1175 }
|
|
1176 }
|
|
1177 llvm_unreachable("arg list didn't provide expected value");
|
|
1178 }
|
|
1179
|
|
1180 std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask) {
|
|
1181 assert(A->getOption().matches(options::OPT_fsanitize_EQ)
|
|
1182 && "Invalid argument in describeSanitizerArg!");
|
|
1183
|
|
1184 std::string Sanitizers;
|
|
1185 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
|
|
1186 if (expandSanitizerGroups(
|
|
1187 parseSanitizerValue(A->getValue(i), /*AllowGroups=*/true)) &
|
|
1188 Mask) {
|
|
1189 if (!Sanitizers.empty())
|
|
1190 Sanitizers += ",";
|
|
1191 Sanitizers += A->getValue(i);
|
|
1192 }
|
|
1193 }
|
|
1194
|
|
1195 assert(!Sanitizers.empty() && "arg didn't provide expected value");
|
|
1196 return "-fsanitize=" + Sanitizers;
|
|
1197 }
|