1*67e74705SXin Li //===--- SanitizerArgs.cpp - Arguments for sanitizer tools ---------------===//
2*67e74705SXin Li //
3*67e74705SXin Li // The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li #include "clang/Driver/SanitizerArgs.h"
10*67e74705SXin Li #include "Tools.h"
11*67e74705SXin Li #include "clang/Basic/Sanitizers.h"
12*67e74705SXin Li #include "clang/Driver/Driver.h"
13*67e74705SXin Li #include "clang/Driver/DriverDiagnostic.h"
14*67e74705SXin Li #include "clang/Driver/Options.h"
15*67e74705SXin Li #include "clang/Driver/ToolChain.h"
16*67e74705SXin Li #include "llvm/ADT/StringExtras.h"
17*67e74705SXin Li #include "llvm/ADT/StringSwitch.h"
18*67e74705SXin Li #include "llvm/Support/FileSystem.h"
19*67e74705SXin Li #include "llvm/Support/Path.h"
20*67e74705SXin Li #include "llvm/Support/SpecialCaseList.h"
21*67e74705SXin Li #include <memory>
22*67e74705SXin Li
23*67e74705SXin Li using namespace clang;
24*67e74705SXin Li using namespace clang::SanitizerKind;
25*67e74705SXin Li using namespace clang::driver;
26*67e74705SXin Li using namespace llvm::opt;
27*67e74705SXin Li
28*67e74705SXin Li enum : SanitizerMask {
29*67e74705SXin Li NeedsUbsanRt = Undefined | Integer | CFI,
30*67e74705SXin Li NeedsUbsanCxxRt = Vptr | CFI,
31*67e74705SXin Li NotAllowedWithTrap = Vptr,
32*67e74705SXin Li RequiresPIE = DataFlow,
33*67e74705SXin Li NeedsUnwindTables = Address | Thread | Memory | DataFlow,
34*67e74705SXin Li SupportsCoverage = Address | Memory | Leak | Undefined | Integer | DataFlow,
35*67e74705SXin Li RecoverableByDefault = Undefined | Integer,
36*67e74705SXin Li Unrecoverable = Unreachable | Return,
37*67e74705SXin Li LegacyFsanitizeRecoverMask = Undefined | Integer,
38*67e74705SXin Li NeedsLTO = CFI,
39*67e74705SXin Li TrappingSupported =
40*67e74705SXin Li (Undefined & ~Vptr) | UnsignedIntegerOverflow | LocalBounds | CFI,
41*67e74705SXin Li TrappingDefault = CFI,
42*67e74705SXin Li CFIClasses = CFIVCall | CFINVCall | CFIDerivedCast | CFIUnrelatedCast,
43*67e74705SXin Li };
44*67e74705SXin Li
45*67e74705SXin Li enum CoverageFeature {
46*67e74705SXin Li CoverageFunc = 1 << 0,
47*67e74705SXin Li CoverageBB = 1 << 1,
48*67e74705SXin Li CoverageEdge = 1 << 2,
49*67e74705SXin Li CoverageIndirCall = 1 << 3,
50*67e74705SXin Li CoverageTraceBB = 1 << 4,
51*67e74705SXin Li CoverageTraceCmp = 1 << 5,
52*67e74705SXin Li Coverage8bitCounters = 1 << 6,
53*67e74705SXin Li CoverageTracePC = 1 << 7,
54*67e74705SXin Li };
55*67e74705SXin Li
56*67e74705SXin Li /// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
57*67e74705SXin Li /// invalid components. Returns a SanitizerMask.
58*67e74705SXin Li static SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
59*67e74705SXin Li bool DiagnoseErrors);
60*67e74705SXin Li
61*67e74705SXin Li /// Parse -f(no-)?sanitize-coverage= flag values, diagnosing any invalid
62*67e74705SXin Li /// components. Returns OR of members of \c CoverageFeature enumeration.
63*67e74705SXin Li static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A);
64*67e74705SXin Li
65*67e74705SXin Li /// Produce an argument string from ArgList \p Args, which shows how it
66*67e74705SXin Li /// provides some sanitizer kind from \p Mask. For example, the argument list
67*67e74705SXin Li /// "-fsanitize=thread,vptr -fsanitize=address" with mask \c NeedsUbsanRt
68*67e74705SXin Li /// would produce "-fsanitize=vptr".
69*67e74705SXin Li static std::string lastArgumentForMask(const Driver &D,
70*67e74705SXin Li const llvm::opt::ArgList &Args,
71*67e74705SXin Li SanitizerMask Mask);
72*67e74705SXin Li
73*67e74705SXin Li /// Produce an argument string from argument \p A, which shows how it provides
74*67e74705SXin Li /// a value in \p Mask. For instance, the argument
75*67e74705SXin Li /// "-fsanitize=address,alignment" with mask \c NeedsUbsanRt would produce
76*67e74705SXin Li /// "-fsanitize=alignment".
77*67e74705SXin Li static std::string describeSanitizeArg(const llvm::opt::Arg *A,
78*67e74705SXin Li SanitizerMask Mask);
79*67e74705SXin Li
80*67e74705SXin Li /// Produce a string containing comma-separated names of sanitizers in \p
81*67e74705SXin Li /// Sanitizers set.
82*67e74705SXin Li static std::string toString(const clang::SanitizerSet &Sanitizers);
83*67e74705SXin Li
getDefaultBlacklist(const Driver & D,SanitizerMask Kinds,std::string & BLPath)84*67e74705SXin Li static bool getDefaultBlacklist(const Driver &D, SanitizerMask Kinds,
85*67e74705SXin Li std::string &BLPath) {
86*67e74705SXin Li const char *BlacklistFile = nullptr;
87*67e74705SXin Li if (Kinds & Address)
88*67e74705SXin Li BlacklistFile = "asan_blacklist.txt";
89*67e74705SXin Li else if (Kinds & Memory)
90*67e74705SXin Li BlacklistFile = "msan_blacklist.txt";
91*67e74705SXin Li else if (Kinds & Thread)
92*67e74705SXin Li BlacklistFile = "tsan_blacklist.txt";
93*67e74705SXin Li else if (Kinds & DataFlow)
94*67e74705SXin Li BlacklistFile = "dfsan_abilist.txt";
95*67e74705SXin Li else if (Kinds & CFI)
96*67e74705SXin Li BlacklistFile = "cfi_blacklist.txt";
97*67e74705SXin Li
98*67e74705SXin Li if (BlacklistFile) {
99*67e74705SXin Li clang::SmallString<64> Path(D.ResourceDir);
100*67e74705SXin Li llvm::sys::path::append(Path, BlacklistFile);
101*67e74705SXin Li BLPath = Path.str();
102*67e74705SXin Li return true;
103*67e74705SXin Li }
104*67e74705SXin Li return false;
105*67e74705SXin Li }
106*67e74705SXin Li
107*67e74705SXin Li /// Sets group bits for every group that has at least one representative already
108*67e74705SXin Li /// enabled in \p Kinds.
setGroupBits(SanitizerMask Kinds)109*67e74705SXin Li static SanitizerMask setGroupBits(SanitizerMask Kinds) {
110*67e74705SXin Li #define SANITIZER(NAME, ID)
111*67e74705SXin Li #define SANITIZER_GROUP(NAME, ID, ALIAS) \
112*67e74705SXin Li if (Kinds & SanitizerKind::ID) \
113*67e74705SXin Li Kinds |= SanitizerKind::ID##Group;
114*67e74705SXin Li #include "clang/Basic/Sanitizers.def"
115*67e74705SXin Li return Kinds;
116*67e74705SXin Li }
117*67e74705SXin Li
parseSanitizeTrapArgs(const Driver & D,const llvm::opt::ArgList & Args)118*67e74705SXin Li static SanitizerMask parseSanitizeTrapArgs(const Driver &D,
119*67e74705SXin Li const llvm::opt::ArgList &Args) {
120*67e74705SXin Li SanitizerMask TrapRemove = 0; // During the loop below, the accumulated set of
121*67e74705SXin Li // sanitizers disabled by the current sanitizer
122*67e74705SXin Li // argument or any argument after it.
123*67e74705SXin Li SanitizerMask TrappingKinds = 0;
124*67e74705SXin Li SanitizerMask TrappingSupportedWithGroups = setGroupBits(TrappingSupported);
125*67e74705SXin Li
126*67e74705SXin Li for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
127*67e74705SXin Li I != E; ++I) {
128*67e74705SXin Li const auto *Arg = *I;
129*67e74705SXin Li if (Arg->getOption().matches(options::OPT_fsanitize_trap_EQ)) {
130*67e74705SXin Li Arg->claim();
131*67e74705SXin Li SanitizerMask Add = parseArgValues(D, Arg, true);
132*67e74705SXin Li Add &= ~TrapRemove;
133*67e74705SXin Li if (SanitizerMask InvalidValues = Add & ~TrappingSupportedWithGroups) {
134*67e74705SXin Li SanitizerSet S;
135*67e74705SXin Li S.Mask = InvalidValues;
136*67e74705SXin Li D.Diag(diag::err_drv_unsupported_option_argument) << "-fsanitize-trap"
137*67e74705SXin Li << toString(S);
138*67e74705SXin Li }
139*67e74705SXin Li TrappingKinds |= expandSanitizerGroups(Add) & ~TrapRemove;
140*67e74705SXin Li } else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) {
141*67e74705SXin Li Arg->claim();
142*67e74705SXin Li TrapRemove |= expandSanitizerGroups(parseArgValues(D, Arg, true));
143*67e74705SXin Li } else if (Arg->getOption().matches(
144*67e74705SXin Li options::OPT_fsanitize_undefined_trap_on_error)) {
145*67e74705SXin Li Arg->claim();
146*67e74705SXin Li TrappingKinds |=
147*67e74705SXin Li expandSanitizerGroups(UndefinedGroup & ~TrapRemove) & ~TrapRemove;
148*67e74705SXin Li } else if (Arg->getOption().matches(
149*67e74705SXin Li options::OPT_fno_sanitize_undefined_trap_on_error)) {
150*67e74705SXin Li Arg->claim();
151*67e74705SXin Li TrapRemove |= expandSanitizerGroups(UndefinedGroup);
152*67e74705SXin Li }
153*67e74705SXin Li }
154*67e74705SXin Li
155*67e74705SXin Li // Apply default trapping behavior.
156*67e74705SXin Li TrappingKinds |= TrappingDefault & ~TrapRemove;
157*67e74705SXin Li
158*67e74705SXin Li return TrappingKinds;
159*67e74705SXin Li }
160*67e74705SXin Li
needsUbsanRt() const161*67e74705SXin Li bool SanitizerArgs::needsUbsanRt() const {
162*67e74705SXin Li return ((Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) ||
163*67e74705SXin Li CoverageFeatures) &&
164*67e74705SXin Li !Sanitizers.has(Address) && !Sanitizers.has(Memory) &&
165*67e74705SXin Li !Sanitizers.has(Thread) && !Sanitizers.has(DataFlow) && !CfiCrossDso;
166*67e74705SXin Li }
167*67e74705SXin Li
needsCfiRt() const168*67e74705SXin Li bool SanitizerArgs::needsCfiRt() const {
169*67e74705SXin Li return !(Sanitizers.Mask & CFI & ~TrapSanitizers.Mask) && CfiCrossDso;
170*67e74705SXin Li }
171*67e74705SXin Li
needsCfiDiagRt() const172*67e74705SXin Li bool SanitizerArgs::needsCfiDiagRt() const {
173*67e74705SXin Li return (Sanitizers.Mask & CFI & ~TrapSanitizers.Mask) && CfiCrossDso;
174*67e74705SXin Li }
175*67e74705SXin Li
requiresPIE() const176*67e74705SXin Li bool SanitizerArgs::requiresPIE() const {
177*67e74705SXin Li return NeedPIE || (Sanitizers.Mask & RequiresPIE);
178*67e74705SXin Li }
179*67e74705SXin Li
needsUnwindTables() const180*67e74705SXin Li bool SanitizerArgs::needsUnwindTables() const {
181*67e74705SXin Li return Sanitizers.Mask & NeedsUnwindTables;
182*67e74705SXin Li }
183*67e74705SXin Li
SanitizerArgs(const ToolChain & TC,const llvm::opt::ArgList & Args)184*67e74705SXin Li SanitizerArgs::SanitizerArgs(const ToolChain &TC,
185*67e74705SXin Li const llvm::opt::ArgList &Args) {
186*67e74705SXin Li SanitizerMask AllRemove = 0; // During the loop below, the accumulated set of
187*67e74705SXin Li // sanitizers disabled by the current sanitizer
188*67e74705SXin Li // argument or any argument after it.
189*67e74705SXin Li SanitizerMask AllAddedKinds = 0; // Mask of all sanitizers ever enabled by
190*67e74705SXin Li // -fsanitize= flags (directly or via group
191*67e74705SXin Li // expansion), some of which may be disabled
192*67e74705SXin Li // later. Used to carefully prune
193*67e74705SXin Li // unused-argument diagnostics.
194*67e74705SXin Li SanitizerMask DiagnosedKinds = 0; // All Kinds we have diagnosed up to now.
195*67e74705SXin Li // Used to deduplicate diagnostics.
196*67e74705SXin Li SanitizerMask Kinds = 0;
197*67e74705SXin Li const SanitizerMask Supported = setGroupBits(TC.getSupportedSanitizers());
198*67e74705SXin Li ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
199*67e74705SXin Li
200*67e74705SXin Li const Driver &D = TC.getDriver();
201*67e74705SXin Li SanitizerMask TrappingKinds = parseSanitizeTrapArgs(D, Args);
202*67e74705SXin Li SanitizerMask InvalidTrappingKinds = TrappingKinds & NotAllowedWithTrap;
203*67e74705SXin Li
204*67e74705SXin Li for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
205*67e74705SXin Li I != E; ++I) {
206*67e74705SXin Li const auto *Arg = *I;
207*67e74705SXin Li if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
208*67e74705SXin Li Arg->claim();
209*67e74705SXin Li SanitizerMask Add = parseArgValues(D, Arg, true);
210*67e74705SXin Li AllAddedKinds |= expandSanitizerGroups(Add);
211*67e74705SXin Li
212*67e74705SXin Li // Avoid diagnosing any sanitizer which is disabled later.
213*67e74705SXin Li Add &= ~AllRemove;
214*67e74705SXin Li // At this point we have not expanded groups, so any unsupported
215*67e74705SXin Li // sanitizers in Add are those which have been explicitly enabled.
216*67e74705SXin Li // Diagnose them.
217*67e74705SXin Li if (SanitizerMask KindsToDiagnose =
218*67e74705SXin Li Add & InvalidTrappingKinds & ~DiagnosedKinds) {
219*67e74705SXin Li std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
220*67e74705SXin Li D.Diag(diag::err_drv_argument_not_allowed_with)
221*67e74705SXin Li << Desc << "-fsanitize-trap=undefined";
222*67e74705SXin Li DiagnosedKinds |= KindsToDiagnose;
223*67e74705SXin Li }
224*67e74705SXin Li Add &= ~InvalidTrappingKinds;
225*67e74705SXin Li if (SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
226*67e74705SXin Li std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
227*67e74705SXin Li D.Diag(diag::err_drv_unsupported_opt_for_target)
228*67e74705SXin Li << Desc << TC.getTriple().str();
229*67e74705SXin Li DiagnosedKinds |= KindsToDiagnose;
230*67e74705SXin Li }
231*67e74705SXin Li Add &= Supported;
232*67e74705SXin Li
233*67e74705SXin Li // Test for -fno-rtti + explicit -fsanitizer=vptr before expanding groups
234*67e74705SXin Li // so we don't error out if -fno-rtti and -fsanitize=undefined were
235*67e74705SXin Li // passed.
236*67e74705SXin Li if (Add & Vptr &&
237*67e74705SXin Li (RTTIMode == ToolChain::RM_DisabledImplicitly ||
238*67e74705SXin Li RTTIMode == ToolChain::RM_DisabledExplicitly)) {
239*67e74705SXin Li if (RTTIMode == ToolChain::RM_DisabledImplicitly)
240*67e74705SXin Li // Warn about not having rtti enabled if the vptr sanitizer is
241*67e74705SXin Li // explicitly enabled
242*67e74705SXin Li D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
243*67e74705SXin Li else {
244*67e74705SXin Li const llvm::opt::Arg *NoRTTIArg = TC.getRTTIArg();
245*67e74705SXin Li assert(NoRTTIArg &&
246*67e74705SXin Li "RTTI disabled explicitly but we have no argument!");
247*67e74705SXin Li D.Diag(diag::err_drv_argument_not_allowed_with)
248*67e74705SXin Li << "-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
249*67e74705SXin Li }
250*67e74705SXin Li
251*67e74705SXin Li // Take out the Vptr sanitizer from the enabled sanitizers
252*67e74705SXin Li AllRemove |= Vptr;
253*67e74705SXin Li }
254*67e74705SXin Li
255*67e74705SXin Li Add = expandSanitizerGroups(Add);
256*67e74705SXin Li // Group expansion may have enabled a sanitizer which is disabled later.
257*67e74705SXin Li Add &= ~AllRemove;
258*67e74705SXin Li // Silently discard any unsupported sanitizers implicitly enabled through
259*67e74705SXin Li // group expansion.
260*67e74705SXin Li Add &= ~InvalidTrappingKinds;
261*67e74705SXin Li Add &= Supported;
262*67e74705SXin Li
263*67e74705SXin Li Kinds |= Add;
264*67e74705SXin Li } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
265*67e74705SXin Li Arg->claim();
266*67e74705SXin Li SanitizerMask Remove = parseArgValues(D, Arg, true);
267*67e74705SXin Li AllRemove |= expandSanitizerGroups(Remove);
268*67e74705SXin Li }
269*67e74705SXin Li }
270*67e74705SXin Li
271*67e74705SXin Li // Enable toolchain specific default sanitizers if not explicitly disabled.
272*67e74705SXin Li Kinds |= TC.getDefaultSanitizers() & ~AllRemove;
273*67e74705SXin Li
274*67e74705SXin Li // We disable the vptr sanitizer if it was enabled by group expansion but RTTI
275*67e74705SXin Li // is disabled.
276*67e74705SXin Li if ((Kinds & Vptr) &&
277*67e74705SXin Li (RTTIMode == ToolChain::RM_DisabledImplicitly ||
278*67e74705SXin Li RTTIMode == ToolChain::RM_DisabledExplicitly)) {
279*67e74705SXin Li Kinds &= ~Vptr;
280*67e74705SXin Li }
281*67e74705SXin Li
282*67e74705SXin Li // Check that LTO is enabled if we need it.
283*67e74705SXin Li if ((Kinds & NeedsLTO) && !D.isUsingLTO()) {
284*67e74705SXin Li D.Diag(diag::err_drv_argument_only_allowed_with)
285*67e74705SXin Li << lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto";
286*67e74705SXin Li }
287*67e74705SXin Li
288*67e74705SXin Li // Report error if there are non-trapping sanitizers that require
289*67e74705SXin Li // c++abi-specific parts of UBSan runtime, and they are not provided by the
290*67e74705SXin Li // toolchain. We don't have a good way to check the latter, so we just
291*67e74705SXin Li // check if the toolchan supports vptr.
292*67e74705SXin Li if (~Supported & Vptr) {
293*67e74705SXin Li SanitizerMask KindsToDiagnose = Kinds & ~TrappingKinds & NeedsUbsanCxxRt;
294*67e74705SXin Li // The runtime library supports the Microsoft C++ ABI, but only well enough
295*67e74705SXin Li // for CFI. FIXME: Remove this once we support vptr on Windows.
296*67e74705SXin Li if (TC.getTriple().isOSWindows())
297*67e74705SXin Li KindsToDiagnose &= ~CFI;
298*67e74705SXin Li if (KindsToDiagnose) {
299*67e74705SXin Li SanitizerSet S;
300*67e74705SXin Li S.Mask = KindsToDiagnose;
301*67e74705SXin Li D.Diag(diag::err_drv_unsupported_opt_for_target)
302*67e74705SXin Li << ("-fno-sanitize-trap=" + toString(S)) << TC.getTriple().str();
303*67e74705SXin Li Kinds &= ~KindsToDiagnose;
304*67e74705SXin Li }
305*67e74705SXin Li }
306*67e74705SXin Li
307*67e74705SXin Li // Warn about incompatible groups of sanitizers.
308*67e74705SXin Li std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
309*67e74705SXin Li std::make_pair(Address, Thread), std::make_pair(Address, Memory),
310*67e74705SXin Li std::make_pair(Thread, Memory), std::make_pair(Leak, Thread),
311*67e74705SXin Li std::make_pair(Leak, Memory), std::make_pair(KernelAddress, Address),
312*67e74705SXin Li std::make_pair(KernelAddress, Leak),
313*67e74705SXin Li std::make_pair(KernelAddress, Thread),
314*67e74705SXin Li std::make_pair(KernelAddress, Memory),
315*67e74705SXin Li std::make_pair(Efficiency, Address),
316*67e74705SXin Li std::make_pair(Efficiency, Leak),
317*67e74705SXin Li std::make_pair(Efficiency, Thread),
318*67e74705SXin Li std::make_pair(Efficiency, Memory),
319*67e74705SXin Li std::make_pair(Efficiency, KernelAddress)};
320*67e74705SXin Li for (auto G : IncompatibleGroups) {
321*67e74705SXin Li SanitizerMask Group = G.first;
322*67e74705SXin Li if (Kinds & Group) {
323*67e74705SXin Li if (SanitizerMask Incompatible = Kinds & G.second) {
324*67e74705SXin Li D.Diag(clang::diag::err_drv_argument_not_allowed_with)
325*67e74705SXin Li << lastArgumentForMask(D, Args, Group)
326*67e74705SXin Li << lastArgumentForMask(D, Args, Incompatible);
327*67e74705SXin Li Kinds &= ~Incompatible;
328*67e74705SXin Li }
329*67e74705SXin Li }
330*67e74705SXin Li }
331*67e74705SXin Li // FIXME: Currently -fsanitize=leak is silently ignored in the presence of
332*67e74705SXin Li // -fsanitize=address. Perhaps it should print an error, or perhaps
333*67e74705SXin Li // -f(-no)sanitize=leak should change whether leak detection is enabled by
334*67e74705SXin Li // default in ASan?
335*67e74705SXin Li
336*67e74705SXin Li // Parse -f(no-)?sanitize-recover flags.
337*67e74705SXin Li SanitizerMask RecoverableKinds = RecoverableByDefault;
338*67e74705SXin Li SanitizerMask DiagnosedUnrecoverableKinds = 0;
339*67e74705SXin Li for (const auto *Arg : Args) {
340*67e74705SXin Li const char *DeprecatedReplacement = nullptr;
341*67e74705SXin Li if (Arg->getOption().matches(options::OPT_fsanitize_recover)) {
342*67e74705SXin Li DeprecatedReplacement =
343*67e74705SXin Li "-fsanitize-recover=undefined,integer' or '-fsanitize-recover=all";
344*67e74705SXin Li RecoverableKinds |= expandSanitizerGroups(LegacyFsanitizeRecoverMask);
345*67e74705SXin Li Arg->claim();
346*67e74705SXin Li } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover)) {
347*67e74705SXin Li DeprecatedReplacement = "-fno-sanitize-recover=undefined,integer' or "
348*67e74705SXin Li "'-fno-sanitize-recover=all";
349*67e74705SXin Li RecoverableKinds &= ~expandSanitizerGroups(LegacyFsanitizeRecoverMask);
350*67e74705SXin Li Arg->claim();
351*67e74705SXin Li } else if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
352*67e74705SXin Li SanitizerMask Add = parseArgValues(D, Arg, true);
353*67e74705SXin Li // Report error if user explicitly tries to recover from unrecoverable
354*67e74705SXin Li // sanitizer.
355*67e74705SXin Li if (SanitizerMask KindsToDiagnose =
356*67e74705SXin Li Add & Unrecoverable & ~DiagnosedUnrecoverableKinds) {
357*67e74705SXin Li SanitizerSet SetToDiagnose;
358*67e74705SXin Li SetToDiagnose.Mask |= KindsToDiagnose;
359*67e74705SXin Li D.Diag(diag::err_drv_unsupported_option_argument)
360*67e74705SXin Li << Arg->getOption().getName() << toString(SetToDiagnose);
361*67e74705SXin Li DiagnosedUnrecoverableKinds |= KindsToDiagnose;
362*67e74705SXin Li }
363*67e74705SXin Li RecoverableKinds |= expandSanitizerGroups(Add);
364*67e74705SXin Li Arg->claim();
365*67e74705SXin Li } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {
366*67e74705SXin Li RecoverableKinds &= ~expandSanitizerGroups(parseArgValues(D, Arg, true));
367*67e74705SXin Li Arg->claim();
368*67e74705SXin Li }
369*67e74705SXin Li if (DeprecatedReplacement) {
370*67e74705SXin Li D.Diag(diag::warn_drv_deprecated_arg) << Arg->getAsString(Args)
371*67e74705SXin Li << DeprecatedReplacement;
372*67e74705SXin Li }
373*67e74705SXin Li }
374*67e74705SXin Li RecoverableKinds &= Kinds;
375*67e74705SXin Li RecoverableKinds &= ~Unrecoverable;
376*67e74705SXin Li
377*67e74705SXin Li TrappingKinds &= Kinds;
378*67e74705SXin Li
379*67e74705SXin Li // Setup blacklist files.
380*67e74705SXin Li // Add default blacklist from resource directory.
381*67e74705SXin Li {
382*67e74705SXin Li std::string BLPath;
383*67e74705SXin Li if (getDefaultBlacklist(D, Kinds, BLPath) && llvm::sys::fs::exists(BLPath))
384*67e74705SXin Li BlacklistFiles.push_back(BLPath);
385*67e74705SXin Li }
386*67e74705SXin Li // Parse -f(no-)sanitize-blacklist options.
387*67e74705SXin Li for (const auto *Arg : Args) {
388*67e74705SXin Li if (Arg->getOption().matches(options::OPT_fsanitize_blacklist)) {
389*67e74705SXin Li Arg->claim();
390*67e74705SXin Li std::string BLPath = Arg->getValue();
391*67e74705SXin Li if (llvm::sys::fs::exists(BLPath)) {
392*67e74705SXin Li BlacklistFiles.push_back(BLPath);
393*67e74705SXin Li ExtraDeps.push_back(BLPath);
394*67e74705SXin Li } else
395*67e74705SXin Li D.Diag(clang::diag::err_drv_no_such_file) << BLPath;
396*67e74705SXin Li
397*67e74705SXin Li } else if (Arg->getOption().matches(options::OPT_fno_sanitize_blacklist)) {
398*67e74705SXin Li Arg->claim();
399*67e74705SXin Li BlacklistFiles.clear();
400*67e74705SXin Li ExtraDeps.clear();
401*67e74705SXin Li }
402*67e74705SXin Li }
403*67e74705SXin Li // Validate blacklists format.
404*67e74705SXin Li {
405*67e74705SXin Li std::string BLError;
406*67e74705SXin Li std::unique_ptr<llvm::SpecialCaseList> SCL(
407*67e74705SXin Li llvm::SpecialCaseList::create(BlacklistFiles, BLError));
408*67e74705SXin Li if (!SCL.get())
409*67e74705SXin Li D.Diag(clang::diag::err_drv_malformed_sanitizer_blacklist) << BLError;
410*67e74705SXin Li }
411*67e74705SXin Li
412*67e74705SXin Li // Parse -f[no-]sanitize-memory-track-origins[=level] options.
413*67e74705SXin Li if (AllAddedKinds & Memory) {
414*67e74705SXin Li if (Arg *A =
415*67e74705SXin Li Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
416*67e74705SXin Li options::OPT_fsanitize_memory_track_origins,
417*67e74705SXin Li options::OPT_fno_sanitize_memory_track_origins)) {
418*67e74705SXin Li if (A->getOption().matches(options::OPT_fsanitize_memory_track_origins)) {
419*67e74705SXin Li MsanTrackOrigins = 2;
420*67e74705SXin Li } else if (A->getOption().matches(
421*67e74705SXin Li options::OPT_fno_sanitize_memory_track_origins)) {
422*67e74705SXin Li MsanTrackOrigins = 0;
423*67e74705SXin Li } else {
424*67e74705SXin Li StringRef S = A->getValue();
425*67e74705SXin Li if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
426*67e74705SXin Li MsanTrackOrigins > 2) {
427*67e74705SXin Li D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
428*67e74705SXin Li }
429*67e74705SXin Li }
430*67e74705SXin Li }
431*67e74705SXin Li MsanUseAfterDtor =
432*67e74705SXin Li Args.hasArg(options::OPT_fsanitize_memory_use_after_dtor);
433*67e74705SXin Li NeedPIE |= !(TC.getTriple().isOSLinux() &&
434*67e74705SXin Li TC.getTriple().getArch() == llvm::Triple::x86_64);
435*67e74705SXin Li }
436*67e74705SXin Li
437*67e74705SXin Li if (AllAddedKinds & CFI) {
438*67e74705SXin Li CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
439*67e74705SXin Li options::OPT_fno_sanitize_cfi_cross_dso, false);
440*67e74705SXin Li // Without PIE, external function address may resolve to a PLT record, which
441*67e74705SXin Li // can not be verified by the target module.
442*67e74705SXin Li NeedPIE |= CfiCrossDso;
443*67e74705SXin Li }
444*67e74705SXin Li
445*67e74705SXin Li Stats = Args.hasFlag(options::OPT_fsanitize_stats,
446*67e74705SXin Li options::OPT_fno_sanitize_stats, false);
447*67e74705SXin Li
448*67e74705SXin Li // Parse -f(no-)?sanitize-coverage flags if coverage is supported by the
449*67e74705SXin Li // enabled sanitizers.
450*67e74705SXin Li for (const auto *Arg : Args) {
451*67e74705SXin Li if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
452*67e74705SXin Li int LegacySanitizeCoverage;
453*67e74705SXin Li if (Arg->getNumValues() == 1 &&
454*67e74705SXin Li !StringRef(Arg->getValue(0))
455*67e74705SXin Li .getAsInteger(0, LegacySanitizeCoverage) &&
456*67e74705SXin Li LegacySanitizeCoverage >= 0 && LegacySanitizeCoverage <= 4) {
457*67e74705SXin Li switch (LegacySanitizeCoverage) {
458*67e74705SXin Li case 0:
459*67e74705SXin Li CoverageFeatures = 0;
460*67e74705SXin Li Arg->claim();
461*67e74705SXin Li break;
462*67e74705SXin Li case 1:
463*67e74705SXin Li D.Diag(diag::warn_drv_deprecated_arg) << Arg->getAsString(Args)
464*67e74705SXin Li << "-fsanitize-coverage=func";
465*67e74705SXin Li CoverageFeatures = CoverageFunc;
466*67e74705SXin Li break;
467*67e74705SXin Li case 2:
468*67e74705SXin Li D.Diag(diag::warn_drv_deprecated_arg) << Arg->getAsString(Args)
469*67e74705SXin Li << "-fsanitize-coverage=bb";
470*67e74705SXin Li CoverageFeatures = CoverageBB;
471*67e74705SXin Li break;
472*67e74705SXin Li case 3:
473*67e74705SXin Li D.Diag(diag::warn_drv_deprecated_arg) << Arg->getAsString(Args)
474*67e74705SXin Li << "-fsanitize-coverage=edge";
475*67e74705SXin Li CoverageFeatures = CoverageEdge;
476*67e74705SXin Li break;
477*67e74705SXin Li case 4:
478*67e74705SXin Li D.Diag(diag::warn_drv_deprecated_arg)
479*67e74705SXin Li << Arg->getAsString(Args)
480*67e74705SXin Li << "-fsanitize-coverage=edge,indirect-calls";
481*67e74705SXin Li CoverageFeatures = CoverageEdge | CoverageIndirCall;
482*67e74705SXin Li break;
483*67e74705SXin Li }
484*67e74705SXin Li continue;
485*67e74705SXin Li }
486*67e74705SXin Li CoverageFeatures |= parseCoverageFeatures(D, Arg);
487*67e74705SXin Li
488*67e74705SXin Li // Disable coverage and not claim the flags if there is at least one
489*67e74705SXin Li // non-supporting sanitizer.
490*67e74705SXin Li if (!(AllAddedKinds & ~setGroupBits(SupportsCoverage))) {
491*67e74705SXin Li Arg->claim();
492*67e74705SXin Li } else {
493*67e74705SXin Li CoverageFeatures = 0;
494*67e74705SXin Li }
495*67e74705SXin Li } else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
496*67e74705SXin Li Arg->claim();
497*67e74705SXin Li CoverageFeatures &= ~parseCoverageFeatures(D, Arg);
498*67e74705SXin Li }
499*67e74705SXin Li }
500*67e74705SXin Li // Choose at most one coverage type: function, bb, or edge.
501*67e74705SXin Li if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageBB))
502*67e74705SXin Li D.Diag(clang::diag::err_drv_argument_not_allowed_with)
503*67e74705SXin Li << "-fsanitize-coverage=func"
504*67e74705SXin Li << "-fsanitize-coverage=bb";
505*67e74705SXin Li if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageEdge))
506*67e74705SXin Li D.Diag(clang::diag::err_drv_argument_not_allowed_with)
507*67e74705SXin Li << "-fsanitize-coverage=func"
508*67e74705SXin Li << "-fsanitize-coverage=edge";
509*67e74705SXin Li if ((CoverageFeatures & CoverageBB) && (CoverageFeatures & CoverageEdge))
510*67e74705SXin Li D.Diag(clang::diag::err_drv_argument_not_allowed_with)
511*67e74705SXin Li << "-fsanitize-coverage=bb"
512*67e74705SXin Li << "-fsanitize-coverage=edge";
513*67e74705SXin Li // Basic block tracing and 8-bit counters require some type of coverage
514*67e74705SXin Li // enabled.
515*67e74705SXin Li int CoverageTypes = CoverageFunc | CoverageBB | CoverageEdge;
516*67e74705SXin Li if ((CoverageFeatures & CoverageTraceBB) &&
517*67e74705SXin Li !(CoverageFeatures & CoverageTypes))
518*67e74705SXin Li D.Diag(clang::diag::err_drv_argument_only_allowed_with)
519*67e74705SXin Li << "-fsanitize-coverage=trace-bb"
520*67e74705SXin Li << "-fsanitize-coverage=(func|bb|edge)";
521*67e74705SXin Li if ((CoverageFeatures & Coverage8bitCounters) &&
522*67e74705SXin Li !(CoverageFeatures & CoverageTypes))
523*67e74705SXin Li D.Diag(clang::diag::err_drv_argument_only_allowed_with)
524*67e74705SXin Li << "-fsanitize-coverage=8bit-counters"
525*67e74705SXin Li << "-fsanitize-coverage=(func|bb|edge)";
526*67e74705SXin Li // trace-pc w/o func/bb/edge implies edge.
527*67e74705SXin Li if ((CoverageFeatures & CoverageTracePC) &&
528*67e74705SXin Li !(CoverageFeatures & CoverageTypes))
529*67e74705SXin Li CoverageFeatures |= CoverageEdge;
530*67e74705SXin Li
531*67e74705SXin Li if (AllAddedKinds & Address) {
532*67e74705SXin Li AsanSharedRuntime =
533*67e74705SXin Li Args.hasArg(options::OPT_shared_libasan) || TC.getTriple().isAndroid();
534*67e74705SXin Li NeedPIE |= TC.getTriple().isAndroid();
535*67e74705SXin Li if (Arg *A =
536*67e74705SXin Li Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
537*67e74705SXin Li StringRef S = A->getValue();
538*67e74705SXin Li // Legal values are 0 and 1, 2, but in future we may add more levels.
539*67e74705SXin Li if (S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
540*67e74705SXin Li AsanFieldPadding > 2) {
541*67e74705SXin Li D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
542*67e74705SXin Li }
543*67e74705SXin Li }
544*67e74705SXin Li
545*67e74705SXin Li if (Arg *WindowsDebugRTArg =
546*67e74705SXin Li Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
547*67e74705SXin Li options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
548*67e74705SXin Li options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
549*67e74705SXin Li switch (WindowsDebugRTArg->getOption().getID()) {
550*67e74705SXin Li case options::OPT__SLASH_MTd:
551*67e74705SXin Li case options::OPT__SLASH_MDd:
552*67e74705SXin Li case options::OPT__SLASH_LDd:
553*67e74705SXin Li D.Diag(clang::diag::err_drv_argument_not_allowed_with)
554*67e74705SXin Li << WindowsDebugRTArg->getAsString(Args)
555*67e74705SXin Li << lastArgumentForMask(D, Args, Address);
556*67e74705SXin Li D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
557*67e74705SXin Li }
558*67e74705SXin Li }
559*67e74705SXin Li }
560*67e74705SXin Li
561*67e74705SXin Li AsanUseAfterScope =
562*67e74705SXin Li Args.hasArg(options::OPT_fsanitize_address_use_after_scope);
563*67e74705SXin Li if (AsanUseAfterScope && !(AllAddedKinds & Address)) {
564*67e74705SXin Li D.Diag(clang::diag::err_drv_argument_only_allowed_with)
565*67e74705SXin Li << "-fsanitize-address-use-after-scope"
566*67e74705SXin Li << "-fsanitize=address";
567*67e74705SXin Li }
568*67e74705SXin Li
569*67e74705SXin Li // Parse -link-cxx-sanitizer flag.
570*67e74705SXin Li LinkCXXRuntimes =
571*67e74705SXin Li Args.hasArg(options::OPT_fsanitize_link_cxx_runtime) || D.CCCIsCXX();
572*67e74705SXin Li
573*67e74705SXin Li // Finally, initialize the set of available and recoverable sanitizers.
574*67e74705SXin Li Sanitizers.Mask |= Kinds;
575*67e74705SXin Li RecoverableSanitizers.Mask |= RecoverableKinds;
576*67e74705SXin Li TrapSanitizers.Mask |= TrappingKinds;
577*67e74705SXin Li }
578*67e74705SXin Li
toString(const clang::SanitizerSet & Sanitizers)579*67e74705SXin Li static std::string toString(const clang::SanitizerSet &Sanitizers) {
580*67e74705SXin Li std::string Res;
581*67e74705SXin Li #define SANITIZER(NAME, ID) \
582*67e74705SXin Li if (Sanitizers.has(ID)) { \
583*67e74705SXin Li if (!Res.empty()) \
584*67e74705SXin Li Res += ","; \
585*67e74705SXin Li Res += NAME; \
586*67e74705SXin Li }
587*67e74705SXin Li #include "clang/Basic/Sanitizers.def"
588*67e74705SXin Li return Res;
589*67e74705SXin Li }
590*67e74705SXin Li
addIncludeLinkerOption(const ToolChain & TC,const llvm::opt::ArgList & Args,llvm::opt::ArgStringList & CmdArgs,StringRef SymbolName)591*67e74705SXin Li static void addIncludeLinkerOption(const ToolChain &TC,
592*67e74705SXin Li const llvm::opt::ArgList &Args,
593*67e74705SXin Li llvm::opt::ArgStringList &CmdArgs,
594*67e74705SXin Li StringRef SymbolName) {
595*67e74705SXin Li SmallString<64> LinkerOptionFlag;
596*67e74705SXin Li LinkerOptionFlag = "--linker-option=/include:";
597*67e74705SXin Li if (TC.getTriple().getArch() == llvm::Triple::x86) {
598*67e74705SXin Li // Win32 mangles C function names with a '_' prefix.
599*67e74705SXin Li LinkerOptionFlag += '_';
600*67e74705SXin Li }
601*67e74705SXin Li LinkerOptionFlag += SymbolName;
602*67e74705SXin Li CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
603*67e74705SXin Li }
604*67e74705SXin Li
addArgs(const ToolChain & TC,const llvm::opt::ArgList & Args,llvm::opt::ArgStringList & CmdArgs,types::ID InputType) const605*67e74705SXin Li void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
606*67e74705SXin Li llvm::opt::ArgStringList &CmdArgs,
607*67e74705SXin Li types::ID InputType) const {
608*67e74705SXin Li // Translate available CoverageFeatures to corresponding clang-cc1 flags.
609*67e74705SXin Li // Do it even if Sanitizers.empty() since some forms of coverage don't require
610*67e74705SXin Li // sanitizers.
611*67e74705SXin Li std::pair<int, const char *> CoverageFlags[] = {
612*67e74705SXin Li std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"),
613*67e74705SXin Li std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"),
614*67e74705SXin Li std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"),
615*67e74705SXin Li std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"),
616*67e74705SXin Li std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"),
617*67e74705SXin Li std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"),
618*67e74705SXin Li std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"),
619*67e74705SXin Li std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc")};
620*67e74705SXin Li for (auto F : CoverageFlags) {
621*67e74705SXin Li if (CoverageFeatures & F.first)
622*67e74705SXin Li CmdArgs.push_back(Args.MakeArgString(F.second));
623*67e74705SXin Li }
624*67e74705SXin Li
625*67e74705SXin Li if (TC.getTriple().isOSWindows() && needsUbsanRt()) {
626*67e74705SXin Li // Instruct the code generator to embed linker directives in the object file
627*67e74705SXin Li // that cause the required runtime libraries to be linked.
628*67e74705SXin Li CmdArgs.push_back(Args.MakeArgString(
629*67e74705SXin Li "--dependent-lib=" + TC.getCompilerRT(Args, "ubsan_standalone")));
630*67e74705SXin Li if (types::isCXX(InputType))
631*67e74705SXin Li CmdArgs.push_back(Args.MakeArgString(
632*67e74705SXin Li "--dependent-lib=" + TC.getCompilerRT(Args, "ubsan_standalone_cxx")));
633*67e74705SXin Li }
634*67e74705SXin Li if (TC.getTriple().isOSWindows() && needsStatsRt()) {
635*67e74705SXin Li CmdArgs.push_back(Args.MakeArgString("--dependent-lib=" +
636*67e74705SXin Li TC.getCompilerRT(Args, "stats_client")));
637*67e74705SXin Li
638*67e74705SXin Li // The main executable must export the stats runtime.
639*67e74705SXin Li // FIXME: Only exporting from the main executable (e.g. based on whether the
640*67e74705SXin Li // translation unit defines main()) would save a little space, but having
641*67e74705SXin Li // multiple copies of the runtime shouldn't hurt.
642*67e74705SXin Li CmdArgs.push_back(Args.MakeArgString("--dependent-lib=" +
643*67e74705SXin Li TC.getCompilerRT(Args, "stats")));
644*67e74705SXin Li addIncludeLinkerOption(TC, Args, CmdArgs, "__sanitizer_stats_register");
645*67e74705SXin Li }
646*67e74705SXin Li
647*67e74705SXin Li if (Sanitizers.empty())
648*67e74705SXin Li return;
649*67e74705SXin Li CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers)));
650*67e74705SXin Li
651*67e74705SXin Li if (!RecoverableSanitizers.empty())
652*67e74705SXin Li CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" +
653*67e74705SXin Li toString(RecoverableSanitizers)));
654*67e74705SXin Li
655*67e74705SXin Li if (!TrapSanitizers.empty())
656*67e74705SXin Li CmdArgs.push_back(
657*67e74705SXin Li Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));
658*67e74705SXin Li
659*67e74705SXin Li for (const auto &BLPath : BlacklistFiles) {
660*67e74705SXin Li SmallString<64> BlacklistOpt("-fsanitize-blacklist=");
661*67e74705SXin Li BlacklistOpt += BLPath;
662*67e74705SXin Li CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
663*67e74705SXin Li }
664*67e74705SXin Li for (const auto &Dep : ExtraDeps) {
665*67e74705SXin Li SmallString<64> ExtraDepOpt("-fdepfile-entry=");
666*67e74705SXin Li ExtraDepOpt += Dep;
667*67e74705SXin Li CmdArgs.push_back(Args.MakeArgString(ExtraDepOpt));
668*67e74705SXin Li }
669*67e74705SXin Li
670*67e74705SXin Li if (MsanTrackOrigins)
671*67e74705SXin Li CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" +
672*67e74705SXin Li llvm::utostr(MsanTrackOrigins)));
673*67e74705SXin Li
674*67e74705SXin Li if (MsanUseAfterDtor)
675*67e74705SXin Li CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-use-after-dtor"));
676*67e74705SXin Li
677*67e74705SXin Li if (CfiCrossDso)
678*67e74705SXin Li CmdArgs.push_back(Args.MakeArgString("-fsanitize-cfi-cross-dso"));
679*67e74705SXin Li
680*67e74705SXin Li if (Stats)
681*67e74705SXin Li CmdArgs.push_back(Args.MakeArgString("-fsanitize-stats"));
682*67e74705SXin Li
683*67e74705SXin Li if (AsanFieldPadding)
684*67e74705SXin Li CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" +
685*67e74705SXin Li llvm::utostr(AsanFieldPadding)));
686*67e74705SXin Li
687*67e74705SXin Li if (AsanUseAfterScope)
688*67e74705SXin Li CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-use-after-scope"));
689*67e74705SXin Li
690*67e74705SXin Li // MSan: Workaround for PR16386.
691*67e74705SXin Li // ASan: This is mainly to help LSan with cases such as
692*67e74705SXin Li // https://code.google.com/p/address-sanitizer/issues/detail?id=373
693*67e74705SXin Li // We can't make this conditional on -fsanitize=leak, as that flag shouldn't
694*67e74705SXin Li // affect compilation.
695*67e74705SXin Li if (Sanitizers.has(Memory) || Sanitizers.has(Address))
696*67e74705SXin Li CmdArgs.push_back(Args.MakeArgString("-fno-assume-sane-operator-new"));
697*67e74705SXin Li
698*67e74705SXin Li // Require -fvisibility= flag on non-Windows when compiling if vptr CFI is
699*67e74705SXin Li // enabled.
700*67e74705SXin Li if (Sanitizers.hasOneOf(CFIClasses) && !TC.getTriple().isOSWindows() &&
701*67e74705SXin Li !Args.hasArg(options::OPT_fvisibility_EQ)) {
702*67e74705SXin Li TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)
703*67e74705SXin Li << lastArgumentForMask(TC.getDriver(), Args,
704*67e74705SXin Li Sanitizers.Mask & CFIClasses)
705*67e74705SXin Li << "-fvisibility=";
706*67e74705SXin Li }
707*67e74705SXin Li }
708*67e74705SXin Li
parseArgValues(const Driver & D,const llvm::opt::Arg * A,bool DiagnoseErrors)709*67e74705SXin Li SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
710*67e74705SXin Li bool DiagnoseErrors) {
711*67e74705SXin Li assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
712*67e74705SXin Li A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
713*67e74705SXin Li A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
714*67e74705SXin Li A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
715*67e74705SXin Li A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
716*67e74705SXin Li A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) &&
717*67e74705SXin Li "Invalid argument in parseArgValues!");
718*67e74705SXin Li SanitizerMask Kinds = 0;
719*67e74705SXin Li for (int i = 0, n = A->getNumValues(); i != n; ++i) {
720*67e74705SXin Li const char *Value = A->getValue(i);
721*67e74705SXin Li SanitizerMask Kind;
722*67e74705SXin Li // Special case: don't accept -fsanitize=all.
723*67e74705SXin Li if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
724*67e74705SXin Li 0 == strcmp("all", Value))
725*67e74705SXin Li Kind = 0;
726*67e74705SXin Li // Similarly, don't accept -fsanitize=efficiency-all.
727*67e74705SXin Li else if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
728*67e74705SXin Li 0 == strcmp("efficiency-all", Value))
729*67e74705SXin Li Kind = 0;
730*67e74705SXin Li else
731*67e74705SXin Li Kind = parseSanitizerValue(Value, /*AllowGroups=*/true);
732*67e74705SXin Li
733*67e74705SXin Li if (Kind)
734*67e74705SXin Li Kinds |= Kind;
735*67e74705SXin Li else if (DiagnoseErrors)
736*67e74705SXin Li D.Diag(clang::diag::err_drv_unsupported_option_argument)
737*67e74705SXin Li << A->getOption().getName() << Value;
738*67e74705SXin Li }
739*67e74705SXin Li return Kinds;
740*67e74705SXin Li }
741*67e74705SXin Li
parseCoverageFeatures(const Driver & D,const llvm::opt::Arg * A)742*67e74705SXin Li int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A) {
743*67e74705SXin Li assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
744*67e74705SXin Li A->getOption().matches(options::OPT_fno_sanitize_coverage));
745*67e74705SXin Li int Features = 0;
746*67e74705SXin Li for (int i = 0, n = A->getNumValues(); i != n; ++i) {
747*67e74705SXin Li const char *Value = A->getValue(i);
748*67e74705SXin Li int F = llvm::StringSwitch<int>(Value)
749*67e74705SXin Li .Case("func", CoverageFunc)
750*67e74705SXin Li .Case("bb", CoverageBB)
751*67e74705SXin Li .Case("edge", CoverageEdge)
752*67e74705SXin Li .Case("indirect-calls", CoverageIndirCall)
753*67e74705SXin Li .Case("trace-bb", CoverageTraceBB)
754*67e74705SXin Li .Case("trace-cmp", CoverageTraceCmp)
755*67e74705SXin Li .Case("8bit-counters", Coverage8bitCounters)
756*67e74705SXin Li .Case("trace-pc", CoverageTracePC)
757*67e74705SXin Li .Default(0);
758*67e74705SXin Li if (F == 0)
759*67e74705SXin Li D.Diag(clang::diag::err_drv_unsupported_option_argument)
760*67e74705SXin Li << A->getOption().getName() << Value;
761*67e74705SXin Li Features |= F;
762*67e74705SXin Li }
763*67e74705SXin Li return Features;
764*67e74705SXin Li }
765*67e74705SXin Li
lastArgumentForMask(const Driver & D,const llvm::opt::ArgList & Args,SanitizerMask Mask)766*67e74705SXin Li std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,
767*67e74705SXin Li SanitizerMask Mask) {
768*67e74705SXin Li for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
769*67e74705SXin Li E = Args.rend();
770*67e74705SXin Li I != E; ++I) {
771*67e74705SXin Li const auto *Arg = *I;
772*67e74705SXin Li if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
773*67e74705SXin Li SanitizerMask AddKinds =
774*67e74705SXin Li expandSanitizerGroups(parseArgValues(D, Arg, false));
775*67e74705SXin Li if (AddKinds & Mask)
776*67e74705SXin Li return describeSanitizeArg(Arg, Mask);
777*67e74705SXin Li } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
778*67e74705SXin Li SanitizerMask RemoveKinds =
779*67e74705SXin Li expandSanitizerGroups(parseArgValues(D, Arg, false));
780*67e74705SXin Li Mask &= ~RemoveKinds;
781*67e74705SXin Li }
782*67e74705SXin Li }
783*67e74705SXin Li llvm_unreachable("arg list didn't provide expected value");
784*67e74705SXin Li }
785*67e74705SXin Li
describeSanitizeArg(const llvm::opt::Arg * A,SanitizerMask Mask)786*67e74705SXin Li std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask) {
787*67e74705SXin Li assert(A->getOption().matches(options::OPT_fsanitize_EQ)
788*67e74705SXin Li && "Invalid argument in describeSanitizerArg!");
789*67e74705SXin Li
790*67e74705SXin Li std::string Sanitizers;
791*67e74705SXin Li for (int i = 0, n = A->getNumValues(); i != n; ++i) {
792*67e74705SXin Li if (expandSanitizerGroups(
793*67e74705SXin Li parseSanitizerValue(A->getValue(i), /*AllowGroups=*/true)) &
794*67e74705SXin Li Mask) {
795*67e74705SXin Li if (!Sanitizers.empty())
796*67e74705SXin Li Sanitizers += ",";
797*67e74705SXin Li Sanitizers += A->getValue(i);
798*67e74705SXin Li }
799*67e74705SXin Li }
800*67e74705SXin Li
801*67e74705SXin Li assert(!Sanitizers.empty() && "arg didn't provide expected value");
802*67e74705SXin Li return "-fsanitize=" + Sanitizers;
803*67e74705SXin Li }
804