blob: 94379ba629005d3a5196888dba932348940a8b15 [file] [log] [blame]
Alexey Samsonovcf055962013-08-08 10:11:02 +00001//===--- SanitizerArgs.cpp - Arguments for sanitizer tools ---------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Alexey Samsonov609213f92013-08-19 09:14:21 +00009#include "clang/Driver/SanitizerArgs.h"
Alexey Samsonovcf055962013-08-08 10:11:02 +000010#include "clang/Driver/Driver.h"
11#include "clang/Driver/DriverDiagnostic.h"
12#include "clang/Driver/Options.h"
13#include "clang/Driver/ToolChain.h"
Evgeniy Stepanov2bfcaab2014-03-20 14:58:36 +000014#include "llvm/ADT/StringExtras.h"
Alexey Samsonovcf055962013-08-08 10:11:02 +000015#include "llvm/ADT/StringSwitch.h"
16#include "llvm/Support/FileSystem.h"
17#include "llvm/Support/Path.h"
Alexey Samsonovb7dd3292014-07-09 19:40:08 +000018#include "llvm/Support/SpecialCaseList.h"
Ahmed Charlesdfca6f92014-03-09 11:36:40 +000019#include <memory>
Alexey Samsonovcf055962013-08-08 10:11:02 +000020
21using namespace clang::driver;
22using namespace llvm::opt;
23
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +000024namespace {
25/// Assign ordinals to possible values of -fsanitize= flag.
26/// We use the ordinal values as bit positions within \c SanitizeKind.
Alexey Samsonov83791e22015-03-03 22:15:32 +000027enum SanitizeOrdinal : uint64_t {
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +000028#define SANITIZER(NAME, ID) SO_##ID,
29#define SANITIZER_GROUP(NAME, ID, ALIAS) SO_##ID##Group,
30#include "clang/Basic/Sanitizers.def"
31 SO_Count
32};
33
34/// Represents a set of sanitizer kinds. It is also used to define:
35/// 1) set of sanitizers each sanitizer group expands into.
36/// 2) set of sanitizers sharing a specific property (e.g.
37/// all sanitizers with zero-base shadow).
Alexey Samsonov83791e22015-03-03 22:15:32 +000038enum SanitizeKind : uint64_t {
39#define SANITIZER(NAME, ID) ID = 1ULL << SO_##ID,
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +000040#define SANITIZER_GROUP(NAME, ID, ALIAS) \
Alexey Samsonov83791e22015-03-03 22:15:32 +000041 ID = ALIAS, ID##Group = 1ULL << SO_##ID##Group,
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +000042#include "clang/Basic/Sanitizers.def"
43 NeedsUbsanRt = Undefined | Integer,
44 NotAllowedWithTrap = Vptr,
Dmitry Vyukov43419a72014-11-21 12:19:01 +000045 RequiresPIE = Memory | DataFlow,
Kostya Serebryany2d88f3d2015-01-06 01:02:48 +000046 NeedsUnwindTables = Address | Thread | Memory | DataFlow,
Kostya Serebryany6fe5fcb2015-03-20 00:06:52 +000047 SupportsCoverage = Address | Memory | Leak | Undefined | Integer | DataFlow,
Alexey Samsonov88459522015-01-12 22:39:12 +000048 RecoverableByDefault = Undefined | Integer,
49 Unrecoverable = Address | Unreachable | Return,
Peter Collingbournea4ccff32015-02-20 20:30:56 +000050 LegacyFsanitizeRecoverMask = Undefined | Integer,
Peter Collingbourne1a7488a2015-04-02 00:23:30 +000051 NeedsLTO = CFI,
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +000052};
Alexey Samsonovdfa908c2015-05-07 22:34:06 +000053
54enum CoverageFeature {
55 CoverageFunc = 1 << 0,
56 CoverageBB = 1 << 1,
57 CoverageEdge = 1 << 2,
58 CoverageIndirCall = 1 << 3,
59 CoverageTraceBB = 1 << 4,
60 CoverageTraceCmp = 1 << 5,
61 Coverage8bitCounters = 1 << 6,
62};
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +000063}
64
65/// Returns true if set of \p Sanitizers contain at least one sanitizer from
66/// \p Kinds.
Alexey Samsonov83791e22015-03-03 22:15:32 +000067static bool hasOneOf(const clang::SanitizerSet &Sanitizers, uint64_t Kinds) {
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +000068#define SANITIZER(NAME, ID) \
69 if (Sanitizers.has(clang::SanitizerKind::ID) && (Kinds & ID)) \
70 return true;
71#include "clang/Basic/Sanitizers.def"
72 return false;
73}
74
75/// Adds all sanitizers from \p Kinds to \p Sanitizers.
Alexey Samsonov83791e22015-03-03 22:15:32 +000076static void addAllOf(clang::SanitizerSet &Sanitizers, uint64_t Kinds) {
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +000077#define SANITIZER(NAME, ID) \
78 if (Kinds & ID) \
79 Sanitizers.set(clang::SanitizerKind::ID, true);
80#include "clang/Basic/Sanitizers.def"
81}
82
Alexey Samsonov83791e22015-03-03 22:15:32 +000083static uint64_t toSanitizeKind(clang::SanitizerKind K) {
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +000084#define SANITIZER(NAME, ID) \
85 if (K == clang::SanitizerKind::ID) \
86 return ID;
87#include "clang/Basic/Sanitizers.def"
88 llvm_unreachable("Invalid SanitizerKind!");
89}
90
91/// Parse a single value from a -fsanitize= or -fno-sanitize= value list.
92/// Returns a member of the \c SanitizeKind enumeration, or \c 0
93/// if \p Value is not known.
Alexey Samsonov83791e22015-03-03 22:15:32 +000094static uint64_t parseValue(const char *Value);
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +000095
96/// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
97/// invalid components. Returns OR of members of \c SanitizeKind enumeration.
Alexey Samsonov83791e22015-03-03 22:15:32 +000098static uint64_t parseArgValues(const Driver &D, const llvm::opt::Arg *A,
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +000099 bool DiagnoseErrors);
100
Alexey Samsonovdfa908c2015-05-07 22:34:06 +0000101/// Parse -f(no-)?sanitize-coverage= flag values, diagnosing any invalid
102/// components. Returns OR of members of \c CoverageFeature enumeration.
103static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A);
104
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +0000105/// Produce an argument string from ArgList \p Args, which shows how it
106/// provides some sanitizer kind from \p Mask. For example, the argument list
107/// "-fsanitize=thread,vptr -fsanitize=address" with mask \c NeedsUbsanRt
108/// would produce "-fsanitize=vptr".
109static std::string lastArgumentForMask(const Driver &D,
110 const llvm::opt::ArgList &Args,
Alexey Samsonov83791e22015-03-03 22:15:32 +0000111 uint64_t Mask);
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +0000112
113static std::string lastArgumentForKind(const Driver &D,
114 const llvm::opt::ArgList &Args,
115 clang::SanitizerKind K) {
116 return lastArgumentForMask(D, Args, toSanitizeKind(K));
117}
118
119/// Produce an argument string from argument \p A, which shows how it provides
120/// a value in \p Mask. For instance, the argument
121/// "-fsanitize=address,alignment" with mask \c NeedsUbsanRt would produce
122/// "-fsanitize=alignment".
Alexey Samsonov83791e22015-03-03 22:15:32 +0000123static std::string describeSanitizeArg(const llvm::opt::Arg *A, uint64_t Mask);
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +0000124
Alexey Samsonov1e715a62014-11-16 20:53:53 +0000125/// Produce a string containing comma-separated names of sanitizers in \p
126/// Sanitizers set.
127static std::string toString(const clang::SanitizerSet &Sanitizers);
128
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +0000129/// For each sanitizer group bit set in \p Kinds, set the bits for sanitizers
130/// this group enables.
Alexey Samsonov83791e22015-03-03 22:15:32 +0000131static uint64_t expandGroups(uint64_t Kinds);
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +0000132
Alexey Samsonov83791e22015-03-03 22:15:32 +0000133static uint64_t getToolchainUnsupportedKinds(const ToolChain &TC) {
Alexey Samsonov1e715a62014-11-16 20:53:53 +0000134 bool IsFreeBSD = TC.getTriple().getOS() == llvm::Triple::FreeBSD;
135 bool IsLinux = TC.getTriple().getOS() == llvm::Triple::Linux;
136 bool IsX86 = TC.getTriple().getArch() == llvm::Triple::x86;
137 bool IsX86_64 = TC.getTriple().getArch() == llvm::Triple::x86_64;
Mohit K. Bhakkadf4c47f62015-01-22 07:21:22 +0000138 bool IsMIPS64 = TC.getTriple().getArch() == llvm::Triple::mips64 ||
139 TC.getTriple().getArch() == llvm::Triple::mips64el;
Alexey Samsonov1e715a62014-11-16 20:53:53 +0000140
Alexey Samsonov83791e22015-03-03 22:15:32 +0000141 uint64_t Unsupported = 0;
Mohit K. Bhakkadf4c47f62015-01-22 07:21:22 +0000142 if (!(IsLinux && (IsX86_64 || IsMIPS64))) {
Alexey Samsonov1e715a62014-11-16 20:53:53 +0000143 Unsupported |= Memory | DataFlow;
144 }
Mohit K. Bhakkad69963e72015-02-23 09:32:35 +0000145 if (!((IsLinux || IsFreeBSD) && (IsX86_64 || IsMIPS64))) {
Alexey Samsonov1e715a62014-11-16 20:53:53 +0000146 Unsupported |= Thread;
147 }
148 if (!(IsLinux && (IsX86 || IsX86_64))) {
149 Unsupported |= Function;
150 }
151 return Unsupported;
152}
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +0000153
Alexey Samsonovecf380e2015-03-20 18:45:06 +0000154static bool getDefaultBlacklist(const Driver &D, uint64_t Kinds,
155 std::string &BLPath) {
156 const char *BlacklistFile = nullptr;
157 if (Kinds & SanitizeKind::Address)
158 BlacklistFile = "asan_blacklist.txt";
159 else if (Kinds & SanitizeKind::Memory)
160 BlacklistFile = "msan_blacklist.txt";
161 else if (Kinds & SanitizeKind::Thread)
162 BlacklistFile = "tsan_blacklist.txt";
163 else if (Kinds & SanitizeKind::DataFlow)
164 BlacklistFile = "dfsan_abilist.txt";
165
166 if (BlacklistFile) {
167 clang::SmallString<64> Path(D.ResourceDir);
168 llvm::sys::path::append(Path, BlacklistFile);
169 BLPath = Path.str();
170 return true;
171 }
172 return false;
173}
174
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +0000175bool SanitizerArgs::needsUbsanRt() const {
Alexey Samsonov31095462015-04-01 22:42:25 +0000176 return !UbsanTrapOnError && hasOneOf(Sanitizers, NeedsUbsanRt) &&
Alexey Samsonovd60832e2015-04-28 00:56:36 +0000177 !Sanitizers.has(SanitizerKind::Address) &&
178 !Sanitizers.has(SanitizerKind::Memory) &&
179 !Sanitizers.has(SanitizerKind::Thread);
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +0000180}
181
Dmitry Vyukov43419a72014-11-21 12:19:01 +0000182bool SanitizerArgs::requiresPIE() const {
183 return AsanZeroBaseShadow || hasOneOf(Sanitizers, RequiresPIE);
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +0000184}
185
186bool SanitizerArgs::needsUnwindTables() const {
187 return hasOneOf(Sanitizers, NeedsUnwindTables);
188}
189
Peter Collingbournea4ccff32015-02-20 20:30:56 +0000190bool SanitizerArgs::needsLTO() const {
Peter Collingbourned2926c92015-03-14 02:42:25 +0000191 return hasOneOf(Sanitizers, NeedsLTO);
Peter Collingbournea4ccff32015-02-20 20:30:56 +0000192}
193
Alexey Samsonovbb14f342013-08-08 11:32:17 +0000194void SanitizerArgs::clear() {
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +0000195 Sanitizers.clear();
Alexey Samsonov88459522015-01-12 22:39:12 +0000196 RecoverableSanitizers.clear();
Alexey Samsonova511cdd2015-02-04 17:40:08 +0000197 BlacklistFiles.clear();
Alexey Samsonovdfa908c2015-05-07 22:34:06 +0000198 CoverageFeatures = 0;
Evgeniy Stepanov2bfcaab2014-03-20 14:58:36 +0000199 MsanTrackOrigins = 0;
Kostya Serebryanyaed71a82014-10-09 17:53:04 +0000200 AsanFieldPadding = 0;
Peter Collingbourne32701642013-11-01 18:16:25 +0000201 AsanZeroBaseShadow = false;
Alexey Samsonovbb14f342013-08-08 11:32:17 +0000202 UbsanTrapOnError = false;
Alexey Samsonovbdfa6c22014-04-01 13:31:10 +0000203 AsanSharedRuntime = false;
Alexey Samsonov90490af2014-08-08 22:47:17 +0000204 LinkCXXRuntimes = false;
Alexey Samsonovbb14f342013-08-08 11:32:17 +0000205}
Alexey Samsonovcf055962013-08-08 10:11:02 +0000206
Peter Collingbourne32701642013-11-01 18:16:25 +0000207SanitizerArgs::SanitizerArgs(const ToolChain &TC,
208 const llvm::opt::ArgList &Args) {
Alexey Samsonovbb14f342013-08-08 11:32:17 +0000209 clear();
Alexey Samsonov83791e22015-03-03 22:15:32 +0000210 uint64_t AllRemove = 0; // During the loop below, the accumulated set of
Peter Collingbourne32701642013-11-01 18:16:25 +0000211 // sanitizers disabled by the current sanitizer
212 // argument or any argument after it.
Alexey Samsonov83791e22015-03-03 22:15:32 +0000213 uint64_t DiagnosedKinds = 0; // All Kinds we have diagnosed up to now.
Peter Collingbourne32701642013-11-01 18:16:25 +0000214 // Used to deduplicate diagnostics.
Alexey Samsonov83791e22015-03-03 22:15:32 +0000215 uint64_t Kinds = 0;
216 uint64_t NotSupported = getToolchainUnsupportedKinds(TC);
Filipe Cabecinhasec5d0e62015-02-19 01:04:49 +0000217 ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
218
Peter Collingbourne32701642013-11-01 18:16:25 +0000219 const Driver &D = TC.getDriver();
220 for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
221 I != E; ++I) {
Alexey Samsonov799f7932014-12-19 02:35:16 +0000222 const auto *Arg = *I;
223 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
224 Arg->claim();
Alexey Samsonov83791e22015-03-03 22:15:32 +0000225 uint64_t Add = parseArgValues(D, Arg, true);
Peter Collingbourne32701642013-11-01 18:16:25 +0000226
Alexey Samsonov799f7932014-12-19 02:35:16 +0000227 // Avoid diagnosing any sanitizer which is disabled later.
228 Add &= ~AllRemove;
229 // At this point we have not expanded groups, so any unsupported
230 // sanitizers in Add are those which have been explicitly enabled.
231 // Diagnose them.
Alexey Samsonov83791e22015-03-03 22:15:32 +0000232 if (uint64_t KindsToDiagnose = Add & NotSupported & ~DiagnosedKinds) {
Alexey Samsonov799f7932014-12-19 02:35:16 +0000233 // Only diagnose the new kinds.
234 std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
235 D.Diag(diag::err_drv_unsupported_opt_for_target)
236 << Desc << TC.getTriple().str();
237 DiagnosedKinds |= KindsToDiagnose;
238 }
239 Add &= ~NotSupported;
Peter Collingbourne32701642013-11-01 18:16:25 +0000240
Filipe Cabecinhasec5d0e62015-02-19 01:04:49 +0000241 // Test for -fno-rtti + explicit -fsanitizer=vptr before expanding groups
242 // so we don't error out if -fno-rtti and -fsanitize=undefined were
243 // passed.
244 if (Add & SanitizeKind::Vptr &&
245 (RTTIMode == ToolChain::RM_DisabledImplicitly ||
246 RTTIMode == ToolChain::RM_DisabledExplicitly)) {
247 if (RTTIMode == ToolChain::RM_DisabledImplicitly)
248 // Warn about not having rtti enabled if the vptr sanitizer is
249 // explicitly enabled
250 D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
251 else {
252 const llvm::opt::Arg *NoRTTIArg = TC.getRTTIArg();
253 assert(NoRTTIArg &&
254 "RTTI disabled explicitly but we have no argument!");
255 D.Diag(diag::err_drv_argument_not_allowed_with)
256 << "-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
257 }
258
259 // Take out the Vptr sanitizer from the enabled sanitizers
260 AllRemove |= SanitizeKind::Vptr;
261 }
262
Alexey Samsonov799f7932014-12-19 02:35:16 +0000263 Add = expandGroups(Add);
264 // Group expansion may have enabled a sanitizer which is disabled later.
265 Add &= ~AllRemove;
266 // Silently discard any unsupported sanitizers implicitly enabled through
267 // group expansion.
268 Add &= ~NotSupported;
Alexey Samsonov1e715a62014-11-16 20:53:53 +0000269
Alexey Samsonov799f7932014-12-19 02:35:16 +0000270 Kinds |= Add;
271 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
272 Arg->claim();
Alexey Samsonov83791e22015-03-03 22:15:32 +0000273 uint64_t Remove = parseArgValues(D, Arg, true);
Alexey Samsonov799f7932014-12-19 02:35:16 +0000274 AllRemove |= expandGroups(Remove);
Alexey Samsonov1e715a62014-11-16 20:53:53 +0000275 }
Alexey Samsonovcf055962013-08-08 10:11:02 +0000276 }
Alexey Samsonov1e715a62014-11-16 20:53:53 +0000277
Filipe Cabecinhasec5d0e62015-02-19 01:04:49 +0000278 // We disable the vptr sanitizer if it was enabled by group expansion but RTTI
279 // is disabled.
Alexey Samsonovecf380e2015-03-20 18:45:06 +0000280 if ((Kinds & SanitizeKind::Vptr) &&
Filipe Cabecinhasec5d0e62015-02-19 01:04:49 +0000281 (RTTIMode == ToolChain::RM_DisabledImplicitly ||
282 RTTIMode == ToolChain::RM_DisabledExplicitly)) {
283 Kinds &= ~SanitizeKind::Vptr;
Filipe Cabecinhasec5d0e62015-02-19 01:04:49 +0000284 }
285
Alexey Samsonovecf380e2015-03-20 18:45:06 +0000286 // Warn about undefined sanitizer options that require runtime support.
287 UbsanTrapOnError =
288 Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
289 options::OPT_fno_sanitize_undefined_trap_on_error, false);
290 if (UbsanTrapOnError && (Kinds & SanitizeKind::NotAllowedWithTrap)) {
291 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
292 << lastArgumentForMask(D, Args, NotAllowedWithTrap)
293 << "-fsanitize-undefined-trap-on-error";
294 Kinds &= ~SanitizeKind::NotAllowedWithTrap;
295 }
296
297 // Warn about incompatible groups of sanitizers.
298 std::pair<uint64_t, uint64_t> IncompatibleGroups[] = {
299 std::make_pair(SanitizeKind::Address, SanitizeKind::Thread),
300 std::make_pair(SanitizeKind::Address, SanitizeKind::Memory),
301 std::make_pair(SanitizeKind::Thread, SanitizeKind::Memory),
302 std::make_pair(SanitizeKind::Leak, SanitizeKind::Thread),
Alexey Samsonovd60832e2015-04-28 00:56:36 +0000303 std::make_pair(SanitizeKind::Leak, SanitizeKind::Memory)};
Alexey Samsonovecf380e2015-03-20 18:45:06 +0000304 for (auto G : IncompatibleGroups) {
305 uint64_t Group = G.first;
306 if (Kinds & Group) {
307 if (uint64_t Incompatible = Kinds & G.second) {
308 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
309 << lastArgumentForMask(D, Args, Group)
310 << lastArgumentForMask(D, Args, Incompatible);
311 Kinds &= ~Incompatible;
312 }
313 }
314 }
315 // FIXME: Currently -fsanitize=leak is silently ignored in the presence of
316 // -fsanitize=address. Perhaps it should print an error, or perhaps
317 // -f(-no)sanitize=leak should change whether leak detection is enabled by
318 // default in ASan?
319
Alexey Samsonov88459522015-01-12 22:39:12 +0000320 // Parse -f(no-)?sanitize-recover flags.
Alexey Samsonov83791e22015-03-03 22:15:32 +0000321 uint64_t RecoverableKinds = RecoverableByDefault;
322 uint64_t DiagnosedUnrecoverableKinds = 0;
Alexey Samsonov88459522015-01-12 22:39:12 +0000323 for (const auto *Arg : Args) {
Alexey Samsonovce2e77c2015-03-11 23:34:25 +0000324 const char *DeprecatedReplacement = nullptr;
Alexey Samsonov88459522015-01-12 22:39:12 +0000325 if (Arg->getOption().matches(options::OPT_fsanitize_recover)) {
Alexey Samsonovce2e77c2015-03-11 23:34:25 +0000326 DeprecatedReplacement = "-fsanitize-recover=undefined,integer";
Alexey Samsonov88459522015-01-12 22:39:12 +0000327 RecoverableKinds |= expandGroups(LegacyFsanitizeRecoverMask);
328 Arg->claim();
329 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover)) {
Alexey Samsonovce2e77c2015-03-11 23:34:25 +0000330 DeprecatedReplacement = "-fno-sanitize-recover=undefined,integer";
Alexey Samsonov88459522015-01-12 22:39:12 +0000331 RecoverableKinds &= ~expandGroups(LegacyFsanitizeRecoverMask);
332 Arg->claim();
333 } else if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
Alexey Samsonov83791e22015-03-03 22:15:32 +0000334 uint64_t Add = parseArgValues(D, Arg, true);
Alexey Samsonov88459522015-01-12 22:39:12 +0000335 // Report error if user explicitly tries to recover from unrecoverable
336 // sanitizer.
Alexey Samsonov83791e22015-03-03 22:15:32 +0000337 if (uint64_t KindsToDiagnose =
Alexey Samsonov88459522015-01-12 22:39:12 +0000338 Add & Unrecoverable & ~DiagnosedUnrecoverableKinds) {
339 SanitizerSet SetToDiagnose;
340 addAllOf(SetToDiagnose, KindsToDiagnose);
341 D.Diag(diag::err_drv_unsupported_option_argument)
342 << Arg->getOption().getName() << toString(SetToDiagnose);
343 DiagnosedUnrecoverableKinds |= KindsToDiagnose;
344 }
345 RecoverableKinds |= expandGroups(Add);
346 Arg->claim();
347 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {
348 RecoverableKinds &= ~expandGroups(parseArgValues(D, Arg, true));
349 Arg->claim();
350 }
Alexey Samsonovce2e77c2015-03-11 23:34:25 +0000351 if (DeprecatedReplacement) {
352 D.Diag(diag::warn_drv_deprecated_arg) << Arg->getAsString(Args)
353 << DeprecatedReplacement;
354 }
Alexey Samsonov88459522015-01-12 22:39:12 +0000355 }
356 RecoverableKinds &= Kinds;
357 RecoverableKinds &= ~Unrecoverable;
Alexey Samsonovcf055962013-08-08 10:11:02 +0000358
Alexey Samsonova511cdd2015-02-04 17:40:08 +0000359 // Setup blacklist files.
360 // Add default blacklist from resource directory.
361 {
Alexey Samsonovcf055962013-08-08 10:11:02 +0000362 std::string BLPath;
Alexey Samsonovecf380e2015-03-20 18:45:06 +0000363 if (getDefaultBlacklist(D, Kinds, BLPath) && llvm::sys::fs::exists(BLPath))
Alexey Samsonova511cdd2015-02-04 17:40:08 +0000364 BlacklistFiles.push_back(BLPath);
365 }
366 // Parse -f(no-)sanitize-blacklist options.
367 for (const auto *Arg : Args) {
368 if (Arg->getOption().matches(options::OPT_fsanitize_blacklist)) {
369 Arg->claim();
370 std::string BLPath = Arg->getValue();
371 if (llvm::sys::fs::exists(BLPath))
372 BlacklistFiles.push_back(BLPath);
373 else
374 D.Diag(clang::diag::err_drv_no_such_file) << BLPath;
375 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_blacklist)) {
376 Arg->claim();
377 BlacklistFiles.clear();
378 }
379 }
380 // Validate blacklists format.
381 {
382 std::string BLError;
383 std::unique_ptr<llvm::SpecialCaseList> SCL(
384 llvm::SpecialCaseList::create(BlacklistFiles, BLError));
385 if (!SCL.get())
386 D.Diag(clang::diag::err_drv_malformed_sanitizer_blacklist) << BLError;
Alexey Samsonovcf055962013-08-08 10:11:02 +0000387 }
388
Evgeniy Stepanov2bfcaab2014-03-20 14:58:36 +0000389 // Parse -f[no-]sanitize-memory-track-origins[=level] options.
Alexey Samsonovecf380e2015-03-20 18:45:06 +0000390 if (Kinds & SanitizeKind::Memory) {
Evgeniy Stepanov2bfcaab2014-03-20 14:58:36 +0000391 if (Arg *A =
392 Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
393 options::OPT_fsanitize_memory_track_origins,
394 options::OPT_fno_sanitize_memory_track_origins)) {
395 if (A->getOption().matches(options::OPT_fsanitize_memory_track_origins)) {
Evgeniy Stepanov6e09bca2015-02-26 15:59:30 +0000396 MsanTrackOrigins = 2;
Evgeniy Stepanov2bfcaab2014-03-20 14:58:36 +0000397 } else if (A->getOption().matches(
398 options::OPT_fno_sanitize_memory_track_origins)) {
399 MsanTrackOrigins = 0;
400 } else {
401 StringRef S = A->getValue();
402 if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
403 MsanTrackOrigins > 2) {
Nico Weberf2a39a72015-04-13 20:03:03 +0000404 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
Evgeniy Stepanov2bfcaab2014-03-20 14:58:36 +0000405 }
406 }
407 }
408 }
409
Alexey Samsonovdfa908c2015-05-07 22:34:06 +0000410 // Parse -f(no-)?sanitize-coverage flags if coverage is supported by the
411 // enabled sanitizers.
Alexey Samsonovecf380e2015-03-20 18:45:06 +0000412 if (Kinds & SanitizeKind::SupportsCoverage) {
Alexey Samsonovdfa908c2015-05-07 22:34:06 +0000413 for (const auto *Arg : Args) {
414 if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
415 Arg->claim();
416 int LegacySanitizeCoverage;
417 if (Arg->getNumValues() == 1 &&
418 !StringRef(Arg->getValue(0))
419 .getAsInteger(0, LegacySanitizeCoverage) &&
420 LegacySanitizeCoverage >= 0 && LegacySanitizeCoverage <= 4) {
421 // TODO: Add deprecation notice for this form.
422 switch (LegacySanitizeCoverage) {
423 case 0:
424 CoverageFeatures = 0;
425 break;
426 case 1:
427 CoverageFeatures = CoverageFunc;
428 break;
429 case 2:
430 CoverageFeatures = CoverageBB;
431 break;
432 case 3:
433 CoverageFeatures = CoverageEdge;
434 break;
435 case 4:
436 CoverageFeatures = CoverageEdge | CoverageIndirCall;
437 break;
438 }
439 continue;
440 }
441 CoverageFeatures |= parseCoverageFeatures(D, Arg);
442 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
443 Arg->claim();
444 CoverageFeatures &= ~parseCoverageFeatures(D, Arg);
445 }
Kostya Serebryany75b4f9e2014-11-11 22:15:07 +0000446 }
447 }
Alexey Samsonovdfa908c2015-05-07 22:34:06 +0000448 // Choose at most one coverage type: function, bb, or edge.
449 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageBB))
450 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
451 << "-fsanitize-coverage=func"
452 << "-fsanitize-coverage=bb";
453 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageEdge))
454 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
455 << "-fsanitize-coverage=func"
456 << "-fsanitize-coverage=edge";
457 if ((CoverageFeatures & CoverageBB) && (CoverageFeatures & CoverageEdge))
458 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
459 << "-fsanitize-coverage=bb"
460 << "-fsanitize-coverage=edge";
461 // Basic block tracing and 8-bit counters require some type of coverage
462 // enabled.
463 int CoverageTypes = CoverageFunc | CoverageBB | CoverageEdge;
464 if ((CoverageFeatures & CoverageTraceBB) &&
465 !(CoverageFeatures & CoverageTypes))
466 D.Diag(clang::diag::err_drv_argument_only_allowed_with)
467 << "-fsanitize-coverage=trace-bb"
468 << "-fsanitize-coverage=(func|bb|edge)";
469 if ((CoverageFeatures & Coverage8bitCounters) &&
470 !(CoverageFeatures & CoverageTypes))
471 D.Diag(clang::diag::err_drv_argument_only_allowed_with)
472 << "-fsanitize-coverage=8bit-counters"
473 << "-fsanitize-coverage=(func|bb|edge)";
Kostya Serebryany75b4f9e2014-11-11 22:15:07 +0000474
Alexey Samsonovecf380e2015-03-20 18:45:06 +0000475 if (Kinds & SanitizeKind::Address) {
Alexey Samsonovbdfa6c22014-04-01 13:31:10 +0000476 AsanSharedRuntime =
Evgeniy Stepanov6f0ae182014-06-05 11:14:00 +0000477 Args.hasArg(options::OPT_shared_libasan) ||
478 (TC.getTriple().getEnvironment() == llvm::Triple::Android);
Peter Collingbourne32701642013-11-01 18:16:25 +0000479 AsanZeroBaseShadow =
Evgeniy Stepanovd04b8612014-01-16 10:19:31 +0000480 (TC.getTriple().getEnvironment() == llvm::Triple::Android);
Kostya Serebryanyaed71a82014-10-09 17:53:04 +0000481 if (Arg *A =
482 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
483 StringRef S = A->getValue();
484 // Legal values are 0 and 1, 2, but in future we may add more levels.
485 if (S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
486 AsanFieldPadding > 2) {
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +0000487 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
Kostya Serebryanyaed71a82014-10-09 17:53:04 +0000488 }
489 }
Ehsan Akhgarie0db1962014-10-14 23:15:44 +0000490
491 if (Arg *WindowsDebugRTArg =
492 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
493 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
494 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
495 switch (WindowsDebugRTArg->getOption().getID()) {
496 case options::OPT__SLASH_MTd:
497 case options::OPT__SLASH_MDd:
498 case options::OPT__SLASH_LDd:
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +0000499 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
Ehsan Akhgarie0db1962014-10-14 23:15:44 +0000500 << WindowsDebugRTArg->getAsString(Args)
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +0000501 << lastArgumentForKind(D, Args, SanitizerKind::Address);
502 D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
Ehsan Akhgarie0db1962014-10-14 23:15:44 +0000503 }
504 }
Alexey Samsonovbdfa6c22014-04-01 13:31:10 +0000505 }
Alexey Samsonov90490af2014-08-08 22:47:17 +0000506
507 // Parse -link-cxx-sanitizer flag.
508 LinkCXXRuntimes =
509 Args.hasArg(options::OPT_fsanitize_link_cxx_runtime) || D.CCCIsCXX();
Alexey Samsonovecf380e2015-03-20 18:45:06 +0000510
511 // Finally, initialize the set of available and recoverable sanitizers.
512 addAllOf(Sanitizers, Kinds);
513 addAllOf(RecoverableSanitizers, RecoverableKinds);
Alexey Samsonovcf055962013-08-08 10:11:02 +0000514}
515
Alexey Samsonov1e715a62014-11-16 20:53:53 +0000516static std::string toString(const clang::SanitizerSet &Sanitizers) {
517 std::string Res;
518#define SANITIZER(NAME, ID) \
519 if (Sanitizers.has(clang::SanitizerKind::ID)) { \
520 if (!Res.empty()) \
521 Res += ","; \
522 Res += NAME; \
523 }
524#include "clang/Basic/Sanitizers.def"
525 return Res;
526}
527
Peter Collingbourne32701642013-11-01 18:16:25 +0000528void SanitizerArgs::addArgs(const llvm::opt::ArgList &Args,
Alexey Samsonovcf055962013-08-08 10:11:02 +0000529 llvm::opt::ArgStringList &CmdArgs) const {
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +0000530 if (Sanitizers.empty())
Alexey Samsonovcf055962013-08-08 10:11:02 +0000531 return;
Alexey Samsonov1e715a62014-11-16 20:53:53 +0000532 CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers)));
533
Alexey Samsonov88459522015-01-12 22:39:12 +0000534 if (!RecoverableSanitizers.empty())
535 CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" +
536 toString(RecoverableSanitizers)));
Alexey Samsonov1e715a62014-11-16 20:53:53 +0000537
538 if (UbsanTrapOnError)
539 CmdArgs.push_back("-fsanitize-undefined-trap-on-error");
540
Alexey Samsonova511cdd2015-02-04 17:40:08 +0000541 for (const auto &BLPath : BlacklistFiles) {
Alexey Samsonovcf055962013-08-08 10:11:02 +0000542 SmallString<64> BlacklistOpt("-fsanitize-blacklist=");
Alexey Samsonova511cdd2015-02-04 17:40:08 +0000543 BlacklistOpt += BLPath;
Alexey Samsonovcf055962013-08-08 10:11:02 +0000544 CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
545 }
546
547 if (MsanTrackOrigins)
Evgeniy Stepanov2bfcaab2014-03-20 14:58:36 +0000548 CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" +
549 llvm::utostr(MsanTrackOrigins)));
Kostya Serebryanyaed71a82014-10-09 17:53:04 +0000550 if (AsanFieldPadding)
551 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" +
552 llvm::utostr(AsanFieldPadding)));
Alexey Samsonovdfa908c2015-05-07 22:34:06 +0000553 // Translate available CoverageFeatures to corresponding clang-cc1 flags.
554 std::pair<int, const char *> CoverageFlags[] = {
555 std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"),
556 std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"),
557 std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"),
558 std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"),
559 std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"),
560 std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"),
561 std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters")};
562 for (auto F : CoverageFlags) {
563 if (CoverageFeatures & F.first)
564 CmdArgs.push_back(Args.MakeArgString(F.second));
Alexey Samsonov3f3b3ab2015-05-07 18:31:29 +0000565 }
Alexey Samsonovdfa908c2015-05-07 22:34:06 +0000566
567
Sergey Matveev2ba87782015-02-17 15:09:33 +0000568 // MSan: Workaround for PR16386.
569 // ASan: This is mainly to help LSan with cases such as
570 // https://code.google.com/p/address-sanitizer/issues/detail?id=373
571 // We can't make this conditional on -fsanitize=leak, as that flag shouldn't
572 // affect compilation.
573 if (Sanitizers.has(SanitizerKind::Memory) ||
574 Sanitizers.has(SanitizerKind::Address))
Alexey Samsonovcf055962013-08-08 10:11:02 +0000575 CmdArgs.push_back(Args.MakeArgString("-fno-assume-sane-operator-new"));
576}
577
Alexey Samsonov83791e22015-03-03 22:15:32 +0000578uint64_t parseValue(const char *Value) {
579 uint64_t ParsedKind = llvm::StringSwitch<SanitizeKind>(Value)
Alexey Samsonovcf055962013-08-08 10:11:02 +0000580#define SANITIZER(NAME, ID) .Case(NAME, ID)
Peter Collingbourne32701642013-11-01 18:16:25 +0000581#define SANITIZER_GROUP(NAME, ID, ALIAS) .Case(NAME, ID##Group)
Alexey Samsonovcf055962013-08-08 10:11:02 +0000582#include "clang/Basic/Sanitizers.def"
583 .Default(SanitizeKind());
Alexey Samsonovcf055962013-08-08 10:11:02 +0000584 return ParsedKind;
585}
586
Alexey Samsonov83791e22015-03-03 22:15:32 +0000587uint64_t expandGroups(uint64_t Kinds) {
Peter Collingbourne32701642013-11-01 18:16:25 +0000588#define SANITIZER(NAME, ID)
589#define SANITIZER_GROUP(NAME, ID, ALIAS) if (Kinds & ID##Group) Kinds |= ID;
590#include "clang/Basic/Sanitizers.def"
591 return Kinds;
592}
593
Alexey Samsonov83791e22015-03-03 22:15:32 +0000594uint64_t parseArgValues(const Driver &D, const llvm::opt::Arg *A,
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +0000595 bool DiagnoseErrors) {
Alexey Samsonov799f7932014-12-19 02:35:16 +0000596 assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
Alexey Samsonov88459522015-01-12 22:39:12 +0000597 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
598 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
599 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) &&
Alexey Samsonov799f7932014-12-19 02:35:16 +0000600 "Invalid argument in parseArgValues!");
Alexey Samsonov83791e22015-03-03 22:15:32 +0000601 uint64_t Kinds = 0;
602 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
603 const char *Value = A->getValue(i);
604 uint64_t Kind;
Alexey Samsonovabd5bea2014-12-19 18:41:43 +0000605 // Special case: don't accept -fsanitize=all.
606 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
607 0 == strcmp("all", Value))
608 Kind = 0;
609 else
610 Kind = parseValue(Value);
611
612 if (Kind)
613 Kinds |= Kind;
Alexey Samsonovcf055962013-08-08 10:11:02 +0000614 else if (DiagnoseErrors)
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +0000615 D.Diag(clang::diag::err_drv_unsupported_option_argument)
Alexey Samsonovabd5bea2014-12-19 18:41:43 +0000616 << A->getOption().getName() << Value;
Alexey Samsonovcf055962013-08-08 10:11:02 +0000617 }
Alexey Samsonovabd5bea2014-12-19 18:41:43 +0000618 return Kinds;
Alexey Samsonovcf055962013-08-08 10:11:02 +0000619}
620
Alexey Samsonovdfa908c2015-05-07 22:34:06 +0000621int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A) {
622 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
623 A->getOption().matches(options::OPT_fno_sanitize_coverage));
624 int Features = 0;
625 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
626 const char *Value = A->getValue(i);
627 int F = llvm::StringSwitch<int>(Value)
628 .Case("func", CoverageFunc)
629 .Case("bb", CoverageBB)
630 .Case("edge", CoverageEdge)
631 .Case("indirect-calls", CoverageIndirCall)
632 .Case("trace-bb", CoverageTraceBB)
633 .Case("trace-cmp", CoverageTraceCmp)
634 .Case("8bit-counters", Coverage8bitCounters)
635 .Default(0);
636 if (F == 0)
637 D.Diag(clang::diag::err_drv_unsupported_option_argument)
638 << A->getOption().getName() << Value;
639 Features |= F;
640 }
641 return Features;
642}
643
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +0000644std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,
Alexey Samsonov83791e22015-03-03 22:15:32 +0000645 uint64_t Mask) {
Alexey Samsonovcf055962013-08-08 10:11:02 +0000646 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
647 E = Args.rend();
648 I != E; ++I) {
Alexey Samsonov799f7932014-12-19 02:35:16 +0000649 const auto *Arg = *I;
650 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
Alexey Samsonov83791e22015-03-03 22:15:32 +0000651 uint64_t AddKinds = expandGroups(parseArgValues(D, Arg, false));
Alexey Samsonov799f7932014-12-19 02:35:16 +0000652 if (AddKinds & Mask)
653 return describeSanitizeArg(Arg, Mask);
654 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
Alexey Samsonov83791e22015-03-03 22:15:32 +0000655 uint64_t RemoveKinds = expandGroups(parseArgValues(D, Arg, false));
Alexey Samsonov799f7932014-12-19 02:35:16 +0000656 Mask &= ~RemoveKinds;
657 }
Alexey Samsonovcf055962013-08-08 10:11:02 +0000658 }
659 llvm_unreachable("arg list didn't provide expected value");
660}
661
Alexey Samsonov83791e22015-03-03 22:15:32 +0000662std::string describeSanitizeArg(const llvm::opt::Arg *A, uint64_t Mask) {
Alexey Samsonov4c12c6c2014-11-14 02:59:20 +0000663 assert(A->getOption().matches(options::OPT_fsanitize_EQ)
664 && "Invalid argument in describeSanitizerArg!");
Alexey Samsonovcf055962013-08-08 10:11:02 +0000665
Peter Collingbourne32701642013-11-01 18:16:25 +0000666 std::string Sanitizers;
Alexey Samsonov83791e22015-03-03 22:15:32 +0000667 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
668 if (expandGroups(parseValue(A->getValue(i))) & Mask) {
Peter Collingbourne32701642013-11-01 18:16:25 +0000669 if (!Sanitizers.empty())
670 Sanitizers += ",";
Alexey Samsonov83791e22015-03-03 22:15:32 +0000671 Sanitizers += A->getValue(i);
Peter Collingbourne32701642013-11-01 18:16:25 +0000672 }
673 }
Alexey Samsonovcf055962013-08-08 10:11:02 +0000674
Peter Collingbourne32701642013-11-01 18:16:25 +0000675 assert(!Sanitizers.empty() && "arg didn't provide expected value");
676 return "-fsanitize=" + Sanitizers;
Alexey Samsonovcf055962013-08-08 10:11:02 +0000677}