annotate clang/lib/Driver/SanitizerArgs.cpp @ 176:de4ac79aef9d

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