1 | |
2 | |
3 | |
4 | |
5 | |
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; |
31 | static const SanitizerMask NeedsUbsanCxxRt = |
32 | SanitizerKind::Vptr | SanitizerKind::CFI; |
33 | static const SanitizerMask NotAllowedWithTrap = SanitizerKind::Vptr; |
34 | static const SanitizerMask NotAllowedWithMinimalRuntime = SanitizerKind::Vptr; |
35 | static const SanitizerMask RequiresPIE = |
36 | SanitizerKind::DataFlow | SanitizerKind::HWAddress | SanitizerKind::Scudo; |
37 | static const SanitizerMask NeedsUnwindTables = |
38 | SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Thread | |
39 | SanitizerKind::Memory | SanitizerKind::DataFlow; |
40 | static const SanitizerMask SupportsCoverage = |
41 | SanitizerKind::Address | SanitizerKind::HWAddress | |
42 | SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress | |
43 | SanitizerKind::Memory | SanitizerKind::KernelMemory | SanitizerKind::Leak | |
44 | SanitizerKind::Undefined | SanitizerKind::Integer | |
45 | SanitizerKind::ImplicitConversion | SanitizerKind::Nullability | |
46 | SanitizerKind::DataFlow | SanitizerKind::Fuzzer | |
47 | SanitizerKind::FuzzerNoLink; |
48 | static const SanitizerMask RecoverableByDefault = |
49 | SanitizerKind::Undefined | SanitizerKind::Integer | |
50 | SanitizerKind::ImplicitConversion | SanitizerKind::Nullability; |
51 | static const SanitizerMask Unrecoverable = |
52 | SanitizerKind::Unreachable | SanitizerKind::Return; |
53 | static const SanitizerMask AlwaysRecoverable = |
54 | SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress; |
55 | static const SanitizerMask LegacyFsanitizeRecoverMask = |
56 | SanitizerKind::Undefined | SanitizerKind::Integer; |
57 | static const SanitizerMask NeedsLTO = SanitizerKind::CFI; |
58 | static const SanitizerMask TrappingSupported = |
59 | (SanitizerKind::Undefined & ~SanitizerKind::Vptr) | |
60 | SanitizerKind::UnsignedIntegerOverflow | SanitizerKind::ImplicitConversion | |
61 | SanitizerKind::Nullability | SanitizerKind::LocalBounds | |
62 | SanitizerKind::CFI; |
63 | static const SanitizerMask TrappingDefault = SanitizerKind::CFI; |
64 | static const SanitizerMask CFIClasses = |
65 | SanitizerKind::CFIVCall | SanitizerKind::CFINVCall | |
66 | SanitizerKind::CFIMFCall | SanitizerKind::CFIDerivedCast | |
67 | SanitizerKind::CFIUnrelatedCast; |
68 | static const SanitizerMask CompatibleWithMinimalRuntime = |
69 | TrappingSupported | SanitizerKind::Scudo | SanitizerKind::ShadowCallStack; |
70 | |
71 | enum CoverageFeature { |
72 | CoverageFunc = 1 << 0, |
73 | CoverageBB = 1 << 1, |
74 | CoverageEdge = 1 << 2, |
75 | CoverageIndirCall = 1 << 3, |
76 | CoverageTraceBB = 1 << 4, |
77 | CoverageTraceCmp = 1 << 5, |
78 | CoverageTraceDiv = 1 << 6, |
79 | CoverageTraceGep = 1 << 7, |
80 | Coverage8bitCounters = 1 << 8, |
81 | CoverageTracePC = 1 << 9, |
82 | CoverageTracePCGuard = 1 << 10, |
83 | CoverageNoPrune = 1 << 11, |
84 | CoverageInline8bitCounters = 1 << 12, |
85 | CoveragePCTable = 1 << 13, |
86 | CoverageStackDepth = 1 << 14, |
87 | }; |
88 | |
89 | |
90 | |
91 | static SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A, |
92 | bool DiagnoseErrors); |
93 | |
94 | |
95 | |
96 | static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A); |
97 | |
98 | |
99 | |
100 | |
101 | |
102 | static std::string lastArgumentForMask(const Driver &D, |
103 | const llvm::opt::ArgList &Args, |
104 | SanitizerMask Mask); |
105 | |
106 | |
107 | |
108 | |
109 | |
110 | static std::string describeSanitizeArg(const llvm::opt::Arg *A, |
111 | SanitizerMask Mask); |
112 | |
113 | |
114 | |
115 | static std::string toString(const clang::SanitizerSet &Sanitizers); |
116 | |
117 | static void addDefaultBlacklists(const Driver &D, SanitizerMask Kinds, |
118 | std::vector<std::string> &BlacklistFiles) { |
119 | struct Blacklist { |
120 | const char *File; |
121 | SanitizerMask Mask; |
122 | } Blacklists[] = {{"asan_blacklist.txt", SanitizerKind::Address}, |
123 | {"hwasan_blacklist.txt", SanitizerKind::HWAddress}, |
124 | {"msan_blacklist.txt", SanitizerKind::Memory}, |
125 | {"tsan_blacklist.txt", SanitizerKind::Thread}, |
126 | {"dfsan_abilist.txt", SanitizerKind::DataFlow}, |
127 | {"cfi_blacklist.txt", SanitizerKind::CFI}, |
128 | {"ubsan_blacklist.txt", SanitizerKind::Undefined | |
129 | SanitizerKind::Integer | |
130 | SanitizerKind::Nullability}}; |
131 | |
132 | for (auto BL : Blacklists) { |
133 | if (!(Kinds & BL.Mask)) |
134 | continue; |
135 | |
136 | clang::SmallString<64> Path(D.ResourceDir); |
137 | llvm::sys::path::append(Path, "share", BL.File); |
138 | if (llvm::sys::fs::exists(Path)) |
139 | BlacklistFiles.push_back(Path.str()); |
140 | else if (BL.Mask == SanitizerKind::CFI) |
141 | |
142 | |
143 | D.Diag(clang::diag::err_drv_no_such_file) << Path; |
144 | } |
145 | } |
146 | |
147 | |
148 | |
149 | static SanitizerMask setGroupBits(SanitizerMask Kinds) { |
150 | #define SANITIZER(NAME, ID) |
151 | #define SANITIZER_GROUP(NAME, ID, ALIAS) \ |
152 | if (Kinds & SanitizerKind::ID) \ |
153 | Kinds |= SanitizerKind::ID##Group; |
154 | #include "clang/Basic/Sanitizers.def" |
155 | return Kinds; |
156 | } |
157 | |
158 | static SanitizerMask parseSanitizeTrapArgs(const Driver &D, |
159 | const llvm::opt::ArgList &Args) { |
160 | SanitizerMask TrapRemove; |
161 | |
162 | |
163 | SanitizerMask TrappingKinds; |
164 | SanitizerMask TrappingSupportedWithGroups = setGroupBits(TrappingSupported); |
165 | |
166 | for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend(); |
167 | I != E; ++I) { |
168 | const auto *Arg = *I; |
169 | if (Arg->getOption().matches(options::OPT_fsanitize_trap_EQ)) { |
170 | Arg->claim(); |
171 | SanitizerMask Add = parseArgValues(D, Arg, true); |
172 | Add &= ~TrapRemove; |
173 | if (SanitizerMask InvalidValues = Add & ~TrappingSupportedWithGroups) { |
174 | SanitizerSet S; |
175 | S.Mask = InvalidValues; |
176 | D.Diag(diag::err_drv_unsupported_option_argument) << "-fsanitize-trap" |
177 | << toString(S); |
178 | } |
179 | TrappingKinds |= expandSanitizerGroups(Add) & ~TrapRemove; |
180 | } else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) { |
181 | Arg->claim(); |
182 | TrapRemove |= expandSanitizerGroups(parseArgValues(D, Arg, true)); |
183 | } else if (Arg->getOption().matches( |
184 | options::OPT_fsanitize_undefined_trap_on_error)) { |
185 | Arg->claim(); |
186 | TrappingKinds |= |
187 | expandSanitizerGroups(SanitizerKind::UndefinedGroup & ~TrapRemove) & |
188 | ~TrapRemove; |
189 | } else if (Arg->getOption().matches( |
190 | options::OPT_fno_sanitize_undefined_trap_on_error)) { |
191 | Arg->claim(); |
192 | TrapRemove |= expandSanitizerGroups(SanitizerKind::UndefinedGroup); |
193 | } |
194 | } |
195 | |
196 | |
197 | TrappingKinds |= TrappingDefault & ~TrapRemove; |
198 | |
199 | return TrappingKinds; |
200 | } |
201 | |
202 | bool SanitizerArgs::needsUbsanRt() const { |
203 | |
204 | if (needsAsanRt() || needsMsanRt() || needsHwasanRt() || needsTsanRt() || |
205 | needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() || |
206 | (needsScudoRt() && !requiresMinimalRuntime())) |
207 | return false; |
208 | |
209 | return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) || |
210 | CoverageFeatures; |
211 | } |
212 | |
213 | bool SanitizerArgs::needsCfiRt() const { |
214 | return !(Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) && |
215 | CfiCrossDso && !ImplicitCfiRuntime; |
216 | } |
217 | |
218 | bool SanitizerArgs::needsCfiDiagRt() const { |
219 | return (Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) && |
220 | CfiCrossDso && !ImplicitCfiRuntime; |
221 | } |
222 | |
223 | bool SanitizerArgs::requiresPIE() const { |
224 | return NeedPIE || (Sanitizers.Mask & RequiresPIE); |
225 | } |
226 | |
227 | bool SanitizerArgs::needsUnwindTables() const { |
228 | return static_cast<bool>(Sanitizers.Mask & NeedsUnwindTables); |
229 | } |
230 | |
231 | bool SanitizerArgs::needsLTO() const { |
232 | return static_cast<bool>(Sanitizers.Mask & NeedsLTO); |
233 | } |
234 | |
235 | SanitizerArgs::SanitizerArgs(const ToolChain &TC, |
236 | const llvm::opt::ArgList &Args) { |
237 | SanitizerMask AllRemove; |
238 | |
239 | |
240 | SanitizerMask AllAddedKinds; |
241 | |
242 | |
243 | |
244 | |
245 | SanitizerMask DiagnosedKinds; |
246 | |
247 | SanitizerMask Kinds; |
248 | const SanitizerMask Supported = setGroupBits(TC.getSupportedSanitizers()); |
249 | |
250 | CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso, |
251 | options::OPT_fno_sanitize_cfi_cross_dso, false); |
252 | |
253 | ToolChain::RTTIMode RTTIMode = TC.getRTTIMode(); |
254 | |
255 | const Driver &D = TC.getDriver(); |
256 | SanitizerMask TrappingKinds = parseSanitizeTrapArgs(D, Args); |
257 | SanitizerMask InvalidTrappingKinds = TrappingKinds & NotAllowedWithTrap; |
258 | |
259 | MinimalRuntime = |
260 | Args.hasFlag(options::OPT_fsanitize_minimal_runtime, |
261 | options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime); |
262 | |
263 | |
264 | Arg *OptLevel = Args.getLastArg(options::OPT_O_Group); |
265 | bool RemoveObjectSizeAtO0 = |
266 | !OptLevel || OptLevel->getOption().matches(options::OPT_O0); |
267 | |
268 | for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend(); |
269 | I != E; ++I) { |
270 | const auto *Arg = *I; |
271 | if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) { |
272 | Arg->claim(); |
273 | SanitizerMask Add = parseArgValues(D, Arg, ); |
274 | |
275 | if (RemoveObjectSizeAtO0) { |
276 | AllRemove |= SanitizerKind::ObjectSize; |
277 | |
278 | |
279 | |
280 | if (Add & SanitizerKind::ObjectSize) |
281 | D.Diag(diag::warn_drv_object_size_disabled_O0) |
282 | << Arg->getAsString(Args); |
283 | } |
284 | |
285 | AllAddedKinds |= expandSanitizerGroups(Add); |
286 | |
287 | |
288 | Add &= ~AllRemove; |
289 | |
290 | |
291 | |
292 | if (SanitizerMask KindsToDiagnose = |
293 | Add & InvalidTrappingKinds & ~DiagnosedKinds) { |
294 | std::string Desc = describeSanitizeArg(*I, KindsToDiagnose); |
295 | D.Diag(diag::err_drv_argument_not_allowed_with) |
296 | << Desc << "-fsanitize-trap=undefined"; |
297 | DiagnosedKinds |= KindsToDiagnose; |
298 | } |
299 | Add &= ~InvalidTrappingKinds; |
300 | |
301 | if (MinimalRuntime) { |
302 | if (SanitizerMask KindsToDiagnose = |
303 | Add & NotAllowedWithMinimalRuntime & ~DiagnosedKinds) { |
304 | std::string Desc = describeSanitizeArg(*I, KindsToDiagnose); |
305 | D.Diag(diag::err_drv_argument_not_allowed_with) |
306 | << Desc << "-fsanitize-minimal-runtime"; |
307 | DiagnosedKinds |= KindsToDiagnose; |
308 | } |
309 | Add &= ~NotAllowedWithMinimalRuntime; |
310 | } |
311 | |
312 | |
313 | |
314 | |
315 | |
316 | |
317 | |
318 | |
319 | |
320 | |
321 | |
322 | if (CfiCrossDso && (Add & SanitizerKind::CFIMFCall & ~DiagnosedKinds)) { |
323 | D.Diag(diag::err_drv_argument_not_allowed_with) |
324 | << "-fsanitize=cfi-mfcall" |
325 | << "-fsanitize-cfi-cross-dso"; |
326 | Add &= ~SanitizerKind::CFIMFCall; |
327 | DiagnosedKinds |= SanitizerKind::CFIMFCall; |
328 | } |
329 | |
330 | if (SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) { |
331 | std::string Desc = describeSanitizeArg(*I, KindsToDiagnose); |
332 | D.Diag(diag::err_drv_unsupported_opt_for_target) |
333 | << Desc << TC.getTriple().str(); |
334 | DiagnosedKinds |= KindsToDiagnose; |
335 | } |
336 | Add &= Supported; |
337 | |
338 | |
339 | |
340 | |
341 | if ((Add & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) { |
342 | if (const llvm::opt::Arg *NoRTTIArg = TC.getRTTIArg()) { |
343 | (0) . __assert_fail ("NoRTTIArg->getOption().matches(options..OPT_fno_rtti) && \"RTTI disabled without -fno-rtti option?\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/SanitizerArgs.cpp", 344, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) && |
344 | (0) . __assert_fail ("NoRTTIArg->getOption().matches(options..OPT_fno_rtti) && \"RTTI disabled without -fno-rtti option?\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/SanitizerArgs.cpp", 344, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "RTTI disabled without -fno-rtti option?"); |
345 | |
346 | |
347 | D.Diag(diag::err_drv_argument_not_allowed_with) |
348 | << "-fsanitize=vptr" << NoRTTIArg->getAsString(Args); |
349 | } else { |
350 | |
351 | |
352 | D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default); |
353 | } |
354 | |
355 | |
356 | AllRemove |= SanitizerKind::Vptr; |
357 | } |
358 | |
359 | Add = expandSanitizerGroups(Add); |
360 | |
361 | Add &= ~AllRemove; |
362 | |
363 | |
364 | Add &= ~InvalidTrappingKinds; |
365 | if (MinimalRuntime) { |
366 | Add &= ~NotAllowedWithMinimalRuntime; |
367 | } |
368 | if (CfiCrossDso) |
369 | Add &= ~SanitizerKind::CFIMFCall; |
370 | Add &= Supported; |
371 | |
372 | if (Add & SanitizerKind::Fuzzer) |
373 | Add |= SanitizerKind::FuzzerNoLink; |
374 | |
375 | |
376 | if (Add & SanitizerKind::FuzzerNoLink) { |
377 | CoverageFeatures |= CoverageInline8bitCounters | CoverageIndirCall | |
378 | CoverageTraceCmp | CoveragePCTable; |
379 | |
380 | if (TC.getTriple().isOSLinux()) |
381 | CoverageFeatures |= CoverageStackDepth; |
382 | } |
383 | |
384 | Kinds |= Add; |
385 | } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) { |
386 | Arg->claim(); |
387 | SanitizerMask Remove = parseArgValues(D, Arg, true); |
388 | AllRemove |= expandSanitizerGroups(Remove); |
389 | } |
390 | } |
391 | |
392 | std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = { |
393 | std::make_pair(SanitizerKind::Address, |
394 | SanitizerKind::Thread | SanitizerKind::Memory), |
395 | std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory), |
396 | std::make_pair(SanitizerKind::Leak, |
397 | SanitizerKind::Thread | SanitizerKind::Memory), |
398 | std::make_pair(SanitizerKind::KernelAddress, |
399 | SanitizerKind::Address | SanitizerKind::Leak | |
400 | SanitizerKind::Thread | SanitizerKind::Memory), |
401 | std::make_pair(SanitizerKind::HWAddress, |
402 | SanitizerKind::Address | SanitizerKind::Thread | |
403 | SanitizerKind::Memory | SanitizerKind::KernelAddress), |
404 | std::make_pair(SanitizerKind::Scudo, |
405 | SanitizerKind::Address | SanitizerKind::HWAddress | |
406 | SanitizerKind::Leak | SanitizerKind::Thread | |
407 | SanitizerKind::Memory | SanitizerKind::KernelAddress), |
408 | std::make_pair(SanitizerKind::SafeStack, |
409 | SanitizerKind::Address | SanitizerKind::HWAddress | |
410 | SanitizerKind::Leak | SanitizerKind::Thread | |
411 | SanitizerKind::Memory | SanitizerKind::KernelAddress), |
412 | std::make_pair(SanitizerKind::KernelHWAddress, |
413 | SanitizerKind::Address | SanitizerKind::HWAddress | |
414 | SanitizerKind::Leak | SanitizerKind::Thread | |
415 | SanitizerKind::Memory | SanitizerKind::KernelAddress | |
416 | SanitizerKind::SafeStack), |
417 | std::make_pair(SanitizerKind::KernelMemory, |
418 | SanitizerKind::Address | SanitizerKind::HWAddress | |
419 | SanitizerKind::Leak | SanitizerKind::Thread | |
420 | SanitizerKind::Memory | SanitizerKind::KernelAddress | |
421 | SanitizerKind::Scudo | SanitizerKind::SafeStack)}; |
422 | |
423 | SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove; |
424 | |
425 | |
426 | |
427 | for (auto G : IncompatibleGroups) { |
428 | SanitizerMask Group = G.first; |
429 | if ((Default & Group) && (Kinds & G.second)) |
430 | Default &= ~Group; |
431 | } |
432 | |
433 | Kinds |= Default; |
434 | |
435 | |
436 | |
437 | if ((Kinds & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) { |
438 | Kinds &= ~SanitizerKind::Vptr; |
439 | } |
440 | |
441 | |
442 | if ((Kinds & NeedsLTO) && !D.isUsingLTO()) { |
443 | D.Diag(diag::err_drv_argument_only_allowed_with) |
444 | << lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto"; |
445 | } |
446 | |
447 | if ((Kinds & SanitizerKind::ShadowCallStack) && |
448 | TC.getTriple().getArch() == llvm::Triple::aarch64 && |
449 | !llvm::AArch64::isX18ReservedByDefault(TC.getTriple()) && |
450 | !Args.hasArg(options::OPT_ffixed_x18)) { |
451 | D.Diag(diag::err_drv_argument_only_allowed_with) |
452 | << lastArgumentForMask(D, Args, Kinds & SanitizerKind::ShadowCallStack) |
453 | << "-ffixed-x18"; |
454 | } |
455 | |
456 | |
457 | |
458 | |
459 | |
460 | if (~Supported & SanitizerKind::Vptr) { |
461 | SanitizerMask KindsToDiagnose = Kinds & ~TrappingKinds & NeedsUbsanCxxRt; |
462 | |
463 | |
464 | if (TC.getTriple().isOSWindows()) |
465 | KindsToDiagnose &= ~SanitizerKind::CFI; |
466 | if (KindsToDiagnose) { |
467 | SanitizerSet S; |
468 | S.Mask = KindsToDiagnose; |
469 | D.Diag(diag::err_drv_unsupported_opt_for_target) |
470 | << ("-fno-sanitize-trap=" + toString(S)) << TC.getTriple().str(); |
471 | Kinds &= ~KindsToDiagnose; |
472 | } |
473 | } |
474 | |
475 | |
476 | for (auto G : IncompatibleGroups) { |
477 | SanitizerMask Group = G.first; |
478 | if (Kinds & Group) { |
479 | if (SanitizerMask Incompatible = Kinds & G.second) { |
480 | D.Diag(clang::diag::err_drv_argument_not_allowed_with) |
481 | << lastArgumentForMask(D, Args, Group) |
482 | << lastArgumentForMask(D, Args, Incompatible); |
483 | Kinds &= ~Incompatible; |
484 | } |
485 | } |
486 | } |
487 | |
488 | |
489 | |
490 | |
491 | |
492 | |
493 | SanitizerMask RecoverableKinds = RecoverableByDefault | AlwaysRecoverable; |
494 | SanitizerMask DiagnosedUnrecoverableKinds; |
495 | SanitizerMask DiagnosedAlwaysRecoverableKinds; |
496 | for (const auto *Arg : Args) { |
497 | const char *DeprecatedReplacement = nullptr; |
498 | if (Arg->getOption().matches(options::OPT_fsanitize_recover)) { |
499 | DeprecatedReplacement = |
500 | "-fsanitize-recover=undefined,integer' or '-fsanitize-recover=all"; |
501 | RecoverableKinds |= expandSanitizerGroups(LegacyFsanitizeRecoverMask); |
502 | Arg->claim(); |
503 | } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover)) { |
504 | DeprecatedReplacement = "-fno-sanitize-recover=undefined,integer' or " |
505 | "'-fno-sanitize-recover=all"; |
506 | RecoverableKinds &= ~expandSanitizerGroups(LegacyFsanitizeRecoverMask); |
507 | Arg->claim(); |
508 | } else if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) { |
509 | SanitizerMask Add = parseArgValues(D, Arg, true); |
510 | |
511 | |
512 | if (SanitizerMask KindsToDiagnose = |
513 | Add & Unrecoverable & ~DiagnosedUnrecoverableKinds) { |
514 | SanitizerSet SetToDiagnose; |
515 | SetToDiagnose.Mask |= KindsToDiagnose; |
516 | D.Diag(diag::err_drv_unsupported_option_argument) |
517 | << Arg->getOption().getName() << toString(SetToDiagnose); |
518 | DiagnosedUnrecoverableKinds |= KindsToDiagnose; |
519 | } |
520 | RecoverableKinds |= expandSanitizerGroups(Add); |
521 | Arg->claim(); |
522 | } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) { |
523 | SanitizerMask Remove = parseArgValues(D, Arg, true); |
524 | |
525 | |
526 | if (SanitizerMask KindsToDiagnose = |
527 | Remove & AlwaysRecoverable & ~DiagnosedAlwaysRecoverableKinds) { |
528 | SanitizerSet SetToDiagnose; |
529 | SetToDiagnose.Mask |= KindsToDiagnose; |
530 | D.Diag(diag::err_drv_unsupported_option_argument) |
531 | << Arg->getOption().getName() << toString(SetToDiagnose); |
532 | DiagnosedAlwaysRecoverableKinds |= KindsToDiagnose; |
533 | } |
534 | RecoverableKinds &= ~expandSanitizerGroups(Remove); |
535 | Arg->claim(); |
536 | } |
537 | if (DeprecatedReplacement) { |
538 | D.Diag(diag::warn_drv_deprecated_arg) << Arg->getAsString(Args) |
539 | << DeprecatedReplacement; |
540 | } |
541 | } |
542 | RecoverableKinds &= Kinds; |
543 | RecoverableKinds &= ~Unrecoverable; |
544 | |
545 | TrappingKinds &= Kinds; |
546 | RecoverableKinds &= ~TrappingKinds; |
547 | |
548 | |
549 | |
550 | addDefaultBlacklists(D, Kinds, BlacklistFiles); |
551 | |
552 | for (const auto *Arg : Args) { |
553 | if (Arg->getOption().matches(options::OPT_fsanitize_blacklist)) { |
554 | Arg->claim(); |
555 | std::string BLPath = Arg->getValue(); |
556 | if (llvm::sys::fs::exists(BLPath)) { |
557 | BlacklistFiles.push_back(BLPath); |
558 | ExtraDeps.push_back(BLPath); |
559 | } else { |
560 | D.Diag(clang::diag::err_drv_no_such_file) << BLPath; |
561 | } |
562 | } else if (Arg->getOption().matches(options::OPT_fno_sanitize_blacklist)) { |
563 | Arg->claim(); |
564 | BlacklistFiles.clear(); |
565 | ExtraDeps.clear(); |
566 | } |
567 | } |
568 | |
569 | { |
570 | std::string BLError; |
571 | std::unique_ptr<llvm::SpecialCaseList> SCL( |
572 | llvm::SpecialCaseList::create(BlacklistFiles, BLError)); |
573 | if (!SCL.get()) |
574 | D.Diag(clang::diag::err_drv_malformed_sanitizer_blacklist) << BLError; |
575 | } |
576 | |
577 | |
578 | if (AllAddedKinds & SanitizerKind::Memory) { |
579 | if (Arg *A = |
580 | Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ, |
581 | options::OPT_fsanitize_memory_track_origins, |
582 | options::OPT_fno_sanitize_memory_track_origins)) { |
583 | if (A->getOption().matches(options::OPT_fsanitize_memory_track_origins)) { |
584 | MsanTrackOrigins = 2; |
585 | } else if (A->getOption().matches( |
586 | options::OPT_fno_sanitize_memory_track_origins)) { |
587 | MsanTrackOrigins = 0; |
588 | } else { |
589 | StringRef S = A->getValue(); |
590 | if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 || |
591 | MsanTrackOrigins > 2) { |
592 | D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S; |
593 | } |
594 | } |
595 | } |
596 | MsanUseAfterDtor = |
597 | Args.hasFlag(options::OPT_fsanitize_memory_use_after_dtor, |
598 | options::OPT_fno_sanitize_memory_use_after_dtor, |
599 | MsanUseAfterDtor); |
600 | NeedPIE |= !(TC.getTriple().isOSLinux() && |
601 | TC.getTriple().getArch() == llvm::Triple::x86_64); |
602 | } else { |
603 | MsanUseAfterDtor = false; |
604 | } |
605 | |
606 | if (AllAddedKinds & SanitizerKind::Thread) { |
607 | TsanMemoryAccess = Args.hasFlag( |
608 | options::OPT_fsanitize_thread_memory_access, |
609 | options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess); |
610 | TsanFuncEntryExit = Args.hasFlag( |
611 | options::OPT_fsanitize_thread_func_entry_exit, |
612 | options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit); |
613 | TsanAtomics = |
614 | Args.hasFlag(options::OPT_fsanitize_thread_atomics, |
615 | options::OPT_fno_sanitize_thread_atomics, TsanAtomics); |
616 | } |
617 | |
618 | if (AllAddedKinds & SanitizerKind::CFI) { |
619 | |
620 | |
621 | NeedPIE |= CfiCrossDso; |
622 | CfiICallGeneralizePointers = |
623 | Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers); |
624 | |
625 | if (CfiCrossDso && CfiICallGeneralizePointers) |
626 | D.Diag(diag::err_drv_argument_not_allowed_with) |
627 | << "-fsanitize-cfi-cross-dso" |
628 | << "-fsanitize-cfi-icall-generalize-pointers"; |
629 | } |
630 | |
631 | Stats = Args.hasFlag(options::OPT_fsanitize_stats, |
632 | options::OPT_fno_sanitize_stats, false); |
633 | |
634 | if (MinimalRuntime) { |
635 | SanitizerMask IncompatibleMask = |
636 | Kinds & ~setGroupBits(CompatibleWithMinimalRuntime); |
637 | if (IncompatibleMask) |
638 | D.Diag(clang::diag::err_drv_argument_not_allowed_with) |
639 | << "-fsanitize-minimal-runtime" |
640 | << lastArgumentForMask(D, Args, IncompatibleMask); |
641 | |
642 | SanitizerMask NonTrappingCfi = Kinds & SanitizerKind::CFI & ~TrappingKinds; |
643 | if (NonTrappingCfi) |
644 | D.Diag(clang::diag::err_drv_argument_only_allowed_with) |
645 | << "fsanitize-minimal-runtime" |
646 | << "fsanitize-trap=cfi"; |
647 | } |
648 | |
649 | |
650 | |
651 | for (const auto *Arg : Args) { |
652 | if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) { |
653 | int LegacySanitizeCoverage; |
654 | if (Arg->getNumValues() == 1 && |
655 | !StringRef(Arg->getValue(0)) |
656 | .getAsInteger(0, LegacySanitizeCoverage)) { |
657 | CoverageFeatures = 0; |
658 | Arg->claim(); |
659 | if (LegacySanitizeCoverage != 0) { |
660 | D.Diag(diag::warn_drv_deprecated_arg) |
661 | << Arg->getAsString(Args) << "-fsanitize-coverage=trace-pc-guard"; |
662 | } |
663 | continue; |
664 | } |
665 | CoverageFeatures |= parseCoverageFeatures(D, Arg); |
666 | |
667 | |
668 | |
669 | if (!(AllAddedKinds & ~AllRemove & ~setGroupBits(SupportsCoverage))) { |
670 | Arg->claim(); |
671 | } else { |
672 | CoverageFeatures = 0; |
673 | } |
674 | } else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) { |
675 | Arg->claim(); |
676 | CoverageFeatures &= ~parseCoverageFeatures(D, Arg); |
677 | } |
678 | } |
679 | |
680 | if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageBB)) |
681 | D.Diag(clang::diag::err_drv_argument_not_allowed_with) |
682 | << "-fsanitize-coverage=func" |
683 | << "-fsanitize-coverage=bb"; |
684 | if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageEdge)) |
685 | D.Diag(clang::diag::err_drv_argument_not_allowed_with) |
686 | << "-fsanitize-coverage=func" |
687 | << "-fsanitize-coverage=edge"; |
688 | if ((CoverageFeatures & CoverageBB) && (CoverageFeatures & CoverageEdge)) |
689 | D.Diag(clang::diag::err_drv_argument_not_allowed_with) |
690 | << "-fsanitize-coverage=bb" |
691 | << "-fsanitize-coverage=edge"; |
692 | |
693 | |
694 | if (CoverageFeatures & CoverageTraceBB) |
695 | D.Diag(clang::diag::warn_drv_deprecated_arg) |
696 | << "-fsanitize-coverage=trace-bb" |
697 | << "-fsanitize-coverage=trace-pc-guard"; |
698 | if (CoverageFeatures & Coverage8bitCounters) |
699 | D.Diag(clang::diag::warn_drv_deprecated_arg) |
700 | << "-fsanitize-coverage=8bit-counters" |
701 | << "-fsanitize-coverage=trace-pc-guard"; |
702 | |
703 | int InsertionPointTypes = CoverageFunc | CoverageBB | CoverageEdge; |
704 | int InstrumentationTypes = |
705 | CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters; |
706 | if ((CoverageFeatures & InsertionPointTypes) && |
707 | !(CoverageFeatures & InstrumentationTypes)) { |
708 | D.Diag(clang::diag::warn_drv_deprecated_arg) |
709 | << "-fsanitize-coverage=[func|bb|edge]" |
710 | << "-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc]"; |
711 | } |
712 | |
713 | |
714 | if (!(CoverageFeatures & InsertionPointTypes)) { |
715 | if (CoverageFeatures & |
716 | (CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters)) |
717 | CoverageFeatures |= CoverageEdge; |
718 | |
719 | if (CoverageFeatures & CoverageStackDepth) |
720 | CoverageFeatures |= CoverageFunc; |
721 | } |
722 | |
723 | SharedRuntime = |
724 | Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan, |
725 | TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() || |
726 | TC.getTriple().isOSDarwin()); |
727 | |
728 | ImplicitCfiRuntime = TC.getTriple().isAndroid(); |
729 | |
730 | if (AllAddedKinds & SanitizerKind::Address) { |
731 | NeedPIE |= TC.getTriple().isOSFuchsia(); |
732 | if (Arg *A = |
733 | Args.getLastArg(options::OPT_fsanitize_address_field_padding)) { |
734 | StringRef S = A->getValue(); |
735 | |
736 | if (S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 || |
737 | AsanFieldPadding > 2) { |
738 | D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S; |
739 | } |
740 | } |
741 | |
742 | if (Arg *WindowsDebugRTArg = |
743 | Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT, |
744 | options::OPT__SLASH_MDd, options::OPT__SLASH_MD, |
745 | options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) { |
746 | switch (WindowsDebugRTArg->getOption().getID()) { |
747 | case options::OPT__SLASH_MTd: |
748 | case options::OPT__SLASH_MDd: |
749 | case options::OPT__SLASH_LDd: |
750 | D.Diag(clang::diag::err_drv_argument_not_allowed_with) |
751 | << WindowsDebugRTArg->getAsString(Args) |
752 | << lastArgumentForMask(D, Args, SanitizerKind::Address); |
753 | D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime); |
754 | } |
755 | } |
756 | |
757 | AsanUseAfterScope = Args.hasFlag( |
758 | options::OPT_fsanitize_address_use_after_scope, |
759 | options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope); |
760 | |
761 | AsanPoisonCustomArrayCookie = Args.hasFlag( |
762 | options::OPT_fsanitize_address_poison_custom_array_cookie, |
763 | options::OPT_fno_sanitize_address_poison_custom_array_cookie, |
764 | AsanPoisonCustomArrayCookie); |
765 | |
766 | |
767 | |
768 | |
769 | AsanGlobalsDeadStripping = |
770 | !TC.getTriple().isOSBinFormatELF() || TC.getTriple().isOSFuchsia() || |
771 | Args.hasArg(options::OPT_fsanitize_address_globals_dead_stripping); |
772 | |
773 | AsanUseOdrIndicator = |
774 | Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator, |
775 | options::OPT_fno_sanitize_address_use_odr_indicator, |
776 | AsanUseOdrIndicator); |
777 | } else { |
778 | AsanUseAfterScope = false; |
779 | } |
780 | |
781 | if (AllAddedKinds & SanitizerKind::HWAddress) { |
782 | if (Arg *HwasanAbiArg = |
783 | Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) { |
784 | HwasanAbi = HwasanAbiArg->getValue(); |
785 | if (HwasanAbi != "platform" && HwasanAbi != "interceptor") |
786 | D.Diag(clang::diag::err_drv_invalid_value) |
787 | << HwasanAbiArg->getAsString(Args) << HwasanAbi; |
788 | } else { |
789 | HwasanAbi = "interceptor"; |
790 | } |
791 | } |
792 | |
793 | if (AllAddedKinds & SanitizerKind::SafeStack) { |
794 | |
795 | SafeStackRuntime = !TC.getTriple().isOSFuchsia(); |
796 | } |
797 | |
798 | |
799 | LinkCXXRuntimes = |
800 | Args.hasArg(options::OPT_fsanitize_link_cxx_runtime) || D.CCCIsCXX(); |
801 | |
802 | |
803 | Sanitizers.Mask |= Kinds; |
804 | RecoverableSanitizers.Mask |= RecoverableKinds; |
805 | TrapSanitizers.Mask |= TrappingKinds; |
806 | (0) . __assert_fail ("!(RecoverableKinds & TrappingKinds) && \"Overlap between recoverable and trapping sanitizers\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/SanitizerArgs.cpp", 807, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!(RecoverableKinds & TrappingKinds) && |
807 | (0) . __assert_fail ("!(RecoverableKinds & TrappingKinds) && \"Overlap between recoverable and trapping sanitizers\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/SanitizerArgs.cpp", 807, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "Overlap between recoverable and trapping sanitizers"); |
808 | } |
809 | |
810 | static std::string toString(const clang::SanitizerSet &Sanitizers) { |
811 | std::string Res; |
812 | #define SANITIZER(NAME, ID) \ |
813 | if (Sanitizers.has(SanitizerKind::ID)) { \ |
814 | if (!Res.empty()) \ |
815 | Res += ","; \ |
816 | Res += NAME; \ |
817 | } |
818 | #include "clang/Basic/Sanitizers.def" |
819 | return Res; |
820 | } |
821 | |
822 | static void addIncludeLinkerOption(const ToolChain &TC, |
823 | const llvm::opt::ArgList &Args, |
824 | llvm::opt::ArgStringList &CmdArgs, |
825 | StringRef SymbolName) { |
826 | SmallString<64> LinkerOptionFlag; |
827 | LinkerOptionFlag = "--linker-option=/include:"; |
828 | if (TC.getTriple().getArch() == llvm::Triple::x86) { |
829 | |
830 | LinkerOptionFlag += '_'; |
831 | } |
832 | LinkerOptionFlag += SymbolName; |
833 | CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag)); |
834 | } |
835 | |
836 | void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, |
837 | llvm::opt::ArgStringList &CmdArgs, |
838 | types::ID InputType) const { |
839 | |
840 | |
841 | |
842 | if (TC.getTriple().isNVPTX()) |
843 | return; |
844 | |
845 | |
846 | |
847 | |
848 | std::pair<int, const char *> CoverageFlags[] = { |
849 | std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"), |
850 | std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"), |
851 | std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"), |
852 | std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"), |
853 | std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"), |
854 | std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"), |
855 | std::make_pair(CoverageTraceDiv, "-fsanitize-coverage-trace-div"), |
856 | std::make_pair(CoverageTraceGep, "-fsanitize-coverage-trace-gep"), |
857 | std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"), |
858 | std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"), |
859 | std::make_pair(CoverageTracePCGuard, "-fsanitize-coverage-trace-pc-guard"), |
860 | std::make_pair(CoverageInline8bitCounters, "-fsanitize-coverage-inline-8bit-counters"), |
861 | std::make_pair(CoveragePCTable, "-fsanitize-coverage-pc-table"), |
862 | std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune"), |
863 | std::make_pair(CoverageStackDepth, "-fsanitize-coverage-stack-depth")}; |
864 | for (auto F : CoverageFlags) { |
865 | if (CoverageFeatures & F.first) |
866 | CmdArgs.push_back(F.second); |
867 | } |
868 | |
869 | if (TC.getTriple().isOSWindows() && needsUbsanRt()) { |
870 | |
871 | |
872 | CmdArgs.push_back(Args.MakeArgString( |
873 | "--dependent-lib=" + TC.getCompilerRT(Args, "ubsan_standalone"))); |
874 | if (types::isCXX(InputType)) |
875 | CmdArgs.push_back(Args.MakeArgString( |
876 | "--dependent-lib=" + TC.getCompilerRT(Args, "ubsan_standalone_cxx"))); |
877 | } |
878 | if (TC.getTriple().isOSWindows() && needsStatsRt()) { |
879 | CmdArgs.push_back(Args.MakeArgString("--dependent-lib=" + |
880 | TC.getCompilerRT(Args, "stats_client"))); |
881 | |
882 | |
883 | |
884 | |
885 | |
886 | CmdArgs.push_back(Args.MakeArgString("--dependent-lib=" + |
887 | TC.getCompilerRT(Args, "stats"))); |
888 | addIncludeLinkerOption(TC, Args, CmdArgs, "__sanitizer_stats_register"); |
889 | } |
890 | |
891 | if (Sanitizers.empty()) |
892 | return; |
893 | CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers))); |
894 | |
895 | if (!RecoverableSanitizers.empty()) |
896 | CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" + |
897 | toString(RecoverableSanitizers))); |
898 | |
899 | if (!TrapSanitizers.empty()) |
900 | CmdArgs.push_back( |
901 | Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers))); |
902 | |
903 | for (const auto &BLPath : BlacklistFiles) { |
904 | SmallString<64> BlacklistOpt("-fsanitize-blacklist="); |
905 | BlacklistOpt += BLPath; |
906 | CmdArgs.push_back(Args.MakeArgString(BlacklistOpt)); |
907 | } |
908 | for (const auto &Dep : ExtraDeps) { |
909 | SmallString<64> ("-fdepfile-entry="); |
910 | ExtraDepOpt += Dep; |
911 | CmdArgs.push_back(Args.MakeArgString(ExtraDepOpt)); |
912 | } |
913 | |
914 | if (MsanTrackOrigins) |
915 | CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" + |
916 | Twine(MsanTrackOrigins))); |
917 | |
918 | if (MsanUseAfterDtor) |
919 | CmdArgs.push_back("-fsanitize-memory-use-after-dtor"); |
920 | |
921 | |
922 | if (!TsanMemoryAccess) { |
923 | CmdArgs.push_back("-mllvm"); |
924 | CmdArgs.push_back("-tsan-instrument-memory-accesses=0"); |
925 | CmdArgs.push_back("-mllvm"); |
926 | CmdArgs.push_back("-tsan-instrument-memintrinsics=0"); |
927 | } |
928 | if (!TsanFuncEntryExit) { |
929 | CmdArgs.push_back("-mllvm"); |
930 | CmdArgs.push_back("-tsan-instrument-func-entry-exit=0"); |
931 | } |
932 | if (!TsanAtomics) { |
933 | CmdArgs.push_back("-mllvm"); |
934 | CmdArgs.push_back("-tsan-instrument-atomics=0"); |
935 | } |
936 | |
937 | if (CfiCrossDso) |
938 | CmdArgs.push_back("-fsanitize-cfi-cross-dso"); |
939 | |
940 | if (CfiICallGeneralizePointers) |
941 | CmdArgs.push_back("-fsanitize-cfi-icall-generalize-pointers"); |
942 | |
943 | if (Stats) |
944 | CmdArgs.push_back("-fsanitize-stats"); |
945 | |
946 | if (MinimalRuntime) |
947 | CmdArgs.push_back("-fsanitize-minimal-runtime"); |
948 | |
949 | if (AsanFieldPadding) |
950 | CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" + |
951 | Twine(AsanFieldPadding))); |
952 | |
953 | if (AsanUseAfterScope) |
954 | CmdArgs.push_back("-fsanitize-address-use-after-scope"); |
955 | |
956 | if (AsanPoisonCustomArrayCookie) |
957 | CmdArgs.push_back("-fsanitize-address-poison-custom-array-cookie"); |
958 | |
959 | if (AsanGlobalsDeadStripping) |
960 | CmdArgs.push_back("-fsanitize-address-globals-dead-stripping"); |
961 | |
962 | if (AsanUseOdrIndicator) |
963 | CmdArgs.push_back("-fsanitize-address-use-odr-indicator"); |
964 | |
965 | if (!HwasanAbi.empty()) { |
966 | CmdArgs.push_back("-default-function-attr"); |
967 | CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi)); |
968 | } |
969 | |
970 | |
971 | |
972 | |
973 | |
974 | |
975 | if (Sanitizers.has(SanitizerKind::Memory) || |
976 | Sanitizers.has(SanitizerKind::Address)) |
977 | CmdArgs.push_back("-fno-assume-sane-operator-new"); |
978 | |
979 | |
980 | |
981 | if (Sanitizers.hasOneOf(CFIClasses) && !TC.getTriple().isOSWindows() && |
982 | !Args.hasArg(options::OPT_fvisibility_EQ)) { |
983 | TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with) |
984 | << lastArgumentForMask(TC.getDriver(), Args, |
985 | Sanitizers.Mask & CFIClasses) |
986 | << "-fvisibility="; |
987 | } |
988 | } |
989 | |
990 | SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A, |
991 | bool DiagnoseErrors) { |
992 | (0) . __assert_fail ("(A->getOption().matches(options..OPT_fsanitize_EQ) || A->getOption().matches(options..OPT_fno_sanitize_EQ) || A->getOption().matches(options..OPT_fsanitize_recover_EQ) || A->getOption().matches(options..OPT_fno_sanitize_recover_EQ) || A->getOption().matches(options..OPT_fsanitize_trap_EQ) || A->getOption().matches(options..OPT_fno_sanitize_trap_EQ)) && \"Invalid argument in parseArgValues!\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/SanitizerArgs.cpp", 998, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert((A->getOption().matches(options::OPT_fsanitize_EQ) || |
993 | (0) . __assert_fail ("(A->getOption().matches(options..OPT_fsanitize_EQ) || A->getOption().matches(options..OPT_fno_sanitize_EQ) || A->getOption().matches(options..OPT_fsanitize_recover_EQ) || A->getOption().matches(options..OPT_fno_sanitize_recover_EQ) || A->getOption().matches(options..OPT_fsanitize_trap_EQ) || A->getOption().matches(options..OPT_fno_sanitize_trap_EQ)) && \"Invalid argument in parseArgValues!\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/SanitizerArgs.cpp", 998, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> A->getOption().matches(options::OPT_fno_sanitize_EQ) || |
994 | (0) . __assert_fail ("(A->getOption().matches(options..OPT_fsanitize_EQ) || A->getOption().matches(options..OPT_fno_sanitize_EQ) || A->getOption().matches(options..OPT_fsanitize_recover_EQ) || A->getOption().matches(options..OPT_fno_sanitize_recover_EQ) || A->getOption().matches(options..OPT_fsanitize_trap_EQ) || A->getOption().matches(options..OPT_fno_sanitize_trap_EQ)) && \"Invalid argument in parseArgValues!\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/SanitizerArgs.cpp", 998, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> A->getOption().matches(options::OPT_fsanitize_recover_EQ) || |
995 | (0) . __assert_fail ("(A->getOption().matches(options..OPT_fsanitize_EQ) || A->getOption().matches(options..OPT_fno_sanitize_EQ) || A->getOption().matches(options..OPT_fsanitize_recover_EQ) || A->getOption().matches(options..OPT_fno_sanitize_recover_EQ) || A->getOption().matches(options..OPT_fsanitize_trap_EQ) || A->getOption().matches(options..OPT_fno_sanitize_trap_EQ)) && \"Invalid argument in parseArgValues!\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/SanitizerArgs.cpp", 998, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) || |
996 | (0) . __assert_fail ("(A->getOption().matches(options..OPT_fsanitize_EQ) || A->getOption().matches(options..OPT_fno_sanitize_EQ) || A->getOption().matches(options..OPT_fsanitize_recover_EQ) || A->getOption().matches(options..OPT_fno_sanitize_recover_EQ) || A->getOption().matches(options..OPT_fsanitize_trap_EQ) || A->getOption().matches(options..OPT_fno_sanitize_trap_EQ)) && \"Invalid argument in parseArgValues!\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/SanitizerArgs.cpp", 998, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> A->getOption().matches(options::OPT_fsanitize_trap_EQ) || |
997 | (0) . __assert_fail ("(A->getOption().matches(options..OPT_fsanitize_EQ) || A->getOption().matches(options..OPT_fno_sanitize_EQ) || A->getOption().matches(options..OPT_fsanitize_recover_EQ) || A->getOption().matches(options..OPT_fno_sanitize_recover_EQ) || A->getOption().matches(options..OPT_fsanitize_trap_EQ) || A->getOption().matches(options..OPT_fno_sanitize_trap_EQ)) && \"Invalid argument in parseArgValues!\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/SanitizerArgs.cpp", 998, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) && |
998 | (0) . __assert_fail ("(A->getOption().matches(options..OPT_fsanitize_EQ) || A->getOption().matches(options..OPT_fno_sanitize_EQ) || A->getOption().matches(options..OPT_fsanitize_recover_EQ) || A->getOption().matches(options..OPT_fno_sanitize_recover_EQ) || A->getOption().matches(options..OPT_fsanitize_trap_EQ) || A->getOption().matches(options..OPT_fno_sanitize_trap_EQ)) && \"Invalid argument in parseArgValues!\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/SanitizerArgs.cpp", 998, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "Invalid argument in parseArgValues!"); |
999 | SanitizerMask Kinds; |
1000 | for (int i = 0, n = A->getNumValues(); i != n; ++i) { |
1001 | const char *Value = A->getValue(i); |
1002 | SanitizerMask Kind; |
1003 | |
1004 | if (A->getOption().matches(options::OPT_fsanitize_EQ) && |
1005 | 0 == strcmp("all", Value)) |
1006 | Kind = SanitizerMask(); |
1007 | else |
1008 | Kind = parseSanitizerValue(Value, ); |
1009 | |
1010 | if (Kind) |
1011 | Kinds |= Kind; |
1012 | else if (DiagnoseErrors) |
1013 | D.Diag(clang::diag::err_drv_unsupported_option_argument) |
1014 | << A->getOption().getName() << Value; |
1015 | } |
1016 | return Kinds; |
1017 | } |
1018 | |
1019 | int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A) { |
1020 | getOption().matches(options..OPT_fsanitize_coverage) || A->getOption().matches(options..OPT_fno_sanitize_coverage)", "/home/seafit/code_projects/clang_source/clang/lib/Driver/SanitizerArgs.cpp", 1021, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(A->getOption().matches(options::OPT_fsanitize_coverage) || |
1021 | getOption().matches(options..OPT_fsanitize_coverage) || A->getOption().matches(options..OPT_fno_sanitize_coverage)", "/home/seafit/code_projects/clang_source/clang/lib/Driver/SanitizerArgs.cpp", 1021, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> A->getOption().matches(options::OPT_fno_sanitize_coverage)); |
1022 | int Features = 0; |
1023 | for (int i = 0, n = A->getNumValues(); i != n; ++i) { |
1024 | const char *Value = A->getValue(i); |
1025 | int F = llvm::StringSwitch<int>(Value) |
1026 | .Case("func", CoverageFunc) |
1027 | .Case("bb", CoverageBB) |
1028 | .Case("edge", CoverageEdge) |
1029 | .Case("indirect-calls", CoverageIndirCall) |
1030 | .Case("trace-bb", CoverageTraceBB) |
1031 | .Case("trace-cmp", CoverageTraceCmp) |
1032 | .Case("trace-div", CoverageTraceDiv) |
1033 | .Case("trace-gep", CoverageTraceGep) |
1034 | .Case("8bit-counters", Coverage8bitCounters) |
1035 | .Case("trace-pc", CoverageTracePC) |
1036 | .Case("trace-pc-guard", CoverageTracePCGuard) |
1037 | .Case("no-prune", CoverageNoPrune) |
1038 | .Case("inline-8bit-counters", CoverageInline8bitCounters) |
1039 | .Case("pc-table", CoveragePCTable) |
1040 | .Case("stack-depth", CoverageStackDepth) |
1041 | .Default(0); |
1042 | if (F == 0) |
1043 | D.Diag(clang::diag::err_drv_unsupported_option_argument) |
1044 | << A->getOption().getName() << Value; |
1045 | Features |= F; |
1046 | } |
1047 | return Features; |
1048 | } |
1049 | |
1050 | std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args, |
1051 | SanitizerMask Mask) { |
1052 | for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(), |
1053 | E = Args.rend(); |
1054 | I != E; ++I) { |
1055 | const auto *Arg = *I; |
1056 | if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) { |
1057 | SanitizerMask AddKinds = |
1058 | expandSanitizerGroups(parseArgValues(D, Arg, false)); |
1059 | if (AddKinds & Mask) |
1060 | return describeSanitizeArg(Arg, Mask); |
1061 | } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) { |
1062 | SanitizerMask RemoveKinds = |
1063 | expandSanitizerGroups(parseArgValues(D, Arg, false)); |
1064 | Mask &= ~RemoveKinds; |
1065 | } |
1066 | } |
1067 | llvm_unreachable("arg list didn't provide expected value"); |
1068 | } |
1069 | |
1070 | std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask) { |
1071 | (0) . __assert_fail ("A->getOption().matches(options..OPT_fsanitize_EQ) && \"Invalid argument in describeSanitizerArg!\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/SanitizerArgs.cpp", 1072, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(A->getOption().matches(options::OPT_fsanitize_EQ) |
1072 | (0) . __assert_fail ("A->getOption().matches(options..OPT_fsanitize_EQ) && \"Invalid argument in describeSanitizerArg!\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/SanitizerArgs.cpp", 1072, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> && "Invalid argument in describeSanitizerArg!"); |
1073 | |
1074 | std::string Sanitizers; |
1075 | for (int i = 0, n = A->getNumValues(); i != n; ++i) { |
1076 | if (expandSanitizerGroups( |
1077 | parseSanitizerValue(A->getValue(i), )) & |
1078 | Mask) { |
1079 | if (!Sanitizers.empty()) |
1080 | Sanitizers += ","; |
1081 | Sanitizers += A->getValue(i); |
1082 | } |
1083 | } |
1084 | |
1085 | (0) . __assert_fail ("!Sanitizers.empty() && \"arg didn't provide expected value\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/SanitizerArgs.cpp", 1085, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!Sanitizers.empty() && "arg didn't provide expected value"); |
1086 | return "-fsanitize=" + Sanitizers; |
1087 | } |
1088 | |