16 #include "llvm/ADT/StringExtras.h"
17 #include "llvm/ADT/StringSwitch.h"
18 #include "llvm/Support/FileSystem.h"
19 #include "llvm/Support/Path.h"
20 #include "llvm/Support/SpecialCaseList.h"
23 using namespace clang;
24 using namespace clang::SanitizerKind;
25 using namespace clang::driver;
26 using namespace llvm::opt;
40 (Undefined & ~Vptr) | UnsignedIntegerOverflow | LocalBounds | CFI,
68 const llvm::opt::ArgList &Args,
83 std::string &BLPath) {
84 const char *BlacklistFile =
nullptr;
86 BlacklistFile =
"asan_blacklist.txt";
87 else if (Kinds & Memory)
88 BlacklistFile =
"msan_blacklist.txt";
89 else if (Kinds & Thread)
90 BlacklistFile =
"tsan_blacklist.txt";
91 else if (Kinds & DataFlow)
92 BlacklistFile =
"dfsan_abilist.txt";
96 llvm::sys::path::append(Path, BlacklistFile);
106 #define SANITIZER(NAME, ID)
107 #define SANITIZER_GROUP(NAME, ID, ALIAS) \
108 if (Kinds & SanitizerKind::ID) \
109 Kinds |= SanitizerKind::ID##Group;
110 #include "clang/Basic/Sanitizers.def"
115 const llvm::opt::ArgList &Args) {
122 for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
124 const auto *Arg = *I;
125 if (Arg->getOption().matches(options::OPT_fsanitize_trap_EQ)) {
129 if (
SanitizerMask InvalidValues = Add & ~TrappingSupportedWithGroups) {
131 S.
Mask = InvalidValues;
132 D.
Diag(diag::err_drv_unsupported_option_argument) <<
"-fsanitize-trap"
136 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) {
139 }
else if (Arg->getOption().matches(
140 options::OPT_fsanitize_undefined_trap_on_error)) {
144 }
else if (Arg->getOption().matches(
145 options::OPT_fno_sanitize_undefined_trap_on_error)) {
154 return TrappingKinds;
157 bool SanitizerArgs::needsUbsanRt()
const {
158 return (Sanitizers.Mask &
NeedsUbsanRt & ~TrapSanitizers.Mask) &&
159 !Sanitizers.has(Address) &&
160 !Sanitizers.has(Memory) &&
161 !Sanitizers.has(Thread);
164 bool SanitizerArgs::requiresPIE()
const {
165 return AsanZeroBaseShadow || (Sanitizers.Mask &
RequiresPIE);
168 bool SanitizerArgs::needsUnwindTables()
const {
174 RecoverableSanitizers.clear();
175 TrapSanitizers.clear();
176 BlacklistFiles.clear();
177 CoverageFeatures = 0;
178 MsanTrackOrigins = 0;
179 MsanUseAfterDtor =
false;
180 AsanFieldPadding = 0;
181 AsanZeroBaseShadow =
false;
182 AsanSharedRuntime =
false;
183 LinkCXXRuntimes =
false;
187 const llvm::opt::ArgList &Args) {
207 for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
209 const auto *Arg = *I;
210 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
221 Add & InvalidTrappingKinds & ~DiagnosedKinds) {
223 D.
Diag(diag::err_drv_argument_not_allowed_with)
224 << Desc <<
"-fsanitize-trap=undefined";
225 DiagnosedKinds |= KindsToDiagnose;
227 Add &= ~InvalidTrappingKinds;
228 if (
SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
230 D.
Diag(diag::err_drv_unsupported_opt_for_target)
232 DiagnosedKinds |= KindsToDiagnose;
240 (RTTIMode == ToolChain::RM_DisabledImplicitly ||
241 RTTIMode == ToolChain::RM_DisabledExplicitly)) {
242 if (RTTIMode == ToolChain::RM_DisabledImplicitly)
245 D.
Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
247 const llvm::opt::Arg *NoRTTIArg = TC.
getRTTIArg();
249 "RTTI disabled explicitly but we have no argument!");
250 D.
Diag(diag::err_drv_argument_not_allowed_with)
251 <<
"-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
263 Add &= ~InvalidTrappingKinds;
267 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
276 if ((Kinds & Vptr) &&
277 (RTTIMode == ToolChain::RM_DisabledImplicitly ||
278 RTTIMode == ToolChain::RM_DisabledExplicitly)) {
284 D.
Diag(diag::err_drv_argument_only_allowed_with)
292 if (~Supported & Vptr) {
297 KindsToDiagnose &= ~CFI;
298 if (KindsToDiagnose) {
300 S.
Mask = KindsToDiagnose;
301 D.
Diag(diag::err_drv_unsupported_opt_for_target)
303 Kinds &= ~KindsToDiagnose;
308 std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
309 std::make_pair(Address, Thread), std::make_pair(Address, Memory),
310 std::make_pair(Thread, Memory), std::make_pair(Leak, Thread),
311 std::make_pair(Leak, Memory), std::make_pair(KernelAddress, Address),
312 std::make_pair(KernelAddress, Leak),
313 std::make_pair(KernelAddress, Thread),
314 std::make_pair(KernelAddress, Memory)};
315 for (
auto G : IncompatibleGroups) {
319 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
322 Kinds &= ~Incompatible;
334 for (
const auto *Arg : Args) {
335 const char *DeprecatedReplacement =
nullptr;
336 if (Arg->getOption().matches(options::OPT_fsanitize_recover)) {
337 DeprecatedReplacement =
"-fsanitize-recover=undefined,integer";
340 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover)) {
341 DeprecatedReplacement =
"-fno-sanitize-recover=undefined,integer";
344 }
else if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
351 SetToDiagnose.
Mask |= KindsToDiagnose;
352 D.
Diag(diag::err_drv_unsupported_option_argument)
353 << Arg->getOption().getName() <<
toString(SetToDiagnose);
354 DiagnosedUnrecoverableKinds |= KindsToDiagnose;
358 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {
362 if (DeprecatedReplacement) {
363 D.
Diag(diag::warn_drv_deprecated_arg) << Arg->getAsString(Args)
364 << DeprecatedReplacement;
367 RecoverableKinds &= Kinds;
370 TrappingKinds &= Kinds;
377 BlacklistFiles.push_back(BLPath);
380 for (
const auto *Arg : Args) {
381 if (Arg->getOption().matches(options::OPT_fsanitize_blacklist)) {
383 std::string BLPath = Arg->getValue();
384 if (llvm::sys::fs::exists(BLPath))
385 BlacklistFiles.push_back(BLPath);
387 D.
Diag(clang::diag::err_drv_no_such_file) << BLPath;
388 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_blacklist)) {
390 BlacklistFiles.clear();
396 std::unique_ptr<llvm::SpecialCaseList> SCL(
399 D.
Diag(clang::diag::err_drv_malformed_sanitizer_blacklist) << BLError;
403 if (AllAddedKinds & Memory) {
405 Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
406 options::OPT_fsanitize_memory_track_origins,
407 options::OPT_fno_sanitize_memory_track_origins)) {
408 if (A->getOption().matches(options::OPT_fsanitize_memory_track_origins)) {
409 MsanTrackOrigins = 2;
410 }
else if (A->getOption().matches(
411 options::OPT_fno_sanitize_memory_track_origins)) {
412 MsanTrackOrigins = 0;
414 StringRef
S = A->getValue();
415 if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
416 MsanTrackOrigins > 2) {
417 D.
Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) <<
S;
422 Args.hasArg(options::OPT_fsanitize_memory_use_after_dtor);
428 for (
const auto *Arg : Args) {
429 if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
431 int LegacySanitizeCoverage;
432 if (Arg->getNumValues() == 1 &&
433 !StringRef(Arg->getValue(0))
434 .getAsInteger(0, LegacySanitizeCoverage) &&
435 LegacySanitizeCoverage >= 0 && LegacySanitizeCoverage <= 4) {
437 switch (LegacySanitizeCoverage) {
439 CoverageFeatures = 0;
457 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
465 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
466 <<
"-fsanitize-coverage=func"
467 <<
"-fsanitize-coverage=bb";
468 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures &
CoverageEdge))
469 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
470 <<
"-fsanitize-coverage=func"
471 <<
"-fsanitize-coverage=edge";
472 if ((CoverageFeatures & CoverageBB) && (CoverageFeatures & CoverageEdge))
473 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
474 <<
"-fsanitize-coverage=bb"
475 <<
"-fsanitize-coverage=edge";
478 int CoverageTypes = CoverageFunc | CoverageBB |
CoverageEdge;
480 !(CoverageFeatures & CoverageTypes))
481 D.
Diag(clang::diag::err_drv_argument_only_allowed_with)
482 <<
"-fsanitize-coverage=trace-bb"
483 <<
"-fsanitize-coverage=(func|bb|edge)";
485 !(CoverageFeatures & CoverageTypes))
486 D.
Diag(clang::diag::err_drv_argument_only_allowed_with)
487 <<
"-fsanitize-coverage=8bit-counters"
488 <<
"-fsanitize-coverage=(func|bb|edge)";
490 if (AllAddedKinds & Address) {
492 Args.hasArg(options::OPT_shared_libasan) ||
493 (TC.
getTriple().getEnvironment() == llvm::Triple::Android);
495 (TC.
getTriple().getEnvironment() == llvm::Triple::Android);
497 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
498 StringRef
S = A->getValue();
500 if (S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
501 AsanFieldPadding > 2) {
502 D.
Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) <<
S;
506 if (Arg *WindowsDebugRTArg =
507 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
508 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
509 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
510 switch (WindowsDebugRTArg->getOption().getID()) {
511 case options::OPT__SLASH_MTd:
512 case options::OPT__SLASH_MDd:
513 case options::OPT__SLASH_LDd:
514 D.
Diag(clang::diag::err_drv_argument_not_allowed_with)
515 << WindowsDebugRTArg->getAsString(Args)
517 D.
Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
524 Args.hasArg(options::OPT_fsanitize_link_cxx_runtime) || D.
CCCIsCXX();
527 Sanitizers.Mask |= Kinds;
528 RecoverableSanitizers.Mask |= RecoverableKinds;
529 TrapSanitizers.Mask |= TrappingKinds;
534 #define SANITIZER(NAME, ID) \
535 if (Sanitizers.has(ID)) { \
540 #include "clang/Basic/Sanitizers.def"
544 void SanitizerArgs::addArgs(
const ToolChain &TC,
const llvm::opt::ArgList &Args,
545 llvm::opt::ArgStringList &CmdArgs,
547 if (Sanitizers.empty())
549 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize=" +
toString(Sanitizers)));
551 if (!RecoverableSanitizers.empty())
552 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-recover=" +
555 if (!TrapSanitizers.empty())
557 Args.MakeArgString(
"-fsanitize-trap=" +
toString(TrapSanitizers)));
559 for (
const auto &BLPath : BlacklistFiles) {
561 BlacklistOpt += BLPath;
562 CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
565 if (MsanTrackOrigins)
566 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-memory-track-origins=" +
567 llvm::utostr(MsanTrackOrigins)));
569 if (MsanUseAfterDtor)
570 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-memory-use-after-dtor"));
572 if (AsanFieldPadding)
573 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-address-field-padding=" +
574 llvm::utostr(AsanFieldPadding)));
576 std::pair<int, const char *> CoverageFlags[] = {
577 std::make_pair(
CoverageFunc,
"-fsanitize-coverage-type=1"),
578 std::make_pair(
CoverageBB,
"-fsanitize-coverage-type=2"),
579 std::make_pair(
CoverageEdge,
"-fsanitize-coverage-type=3"),
584 for (
auto F : CoverageFlags) {
585 if (CoverageFeatures & F.first)
586 CmdArgs.push_back(Args.MakeArgString(F.second));
595 if (Sanitizers.has(Memory) || Sanitizers.has(Address))
596 CmdArgs.push_back(Args.MakeArgString(
"-fno-assume-sane-operator-new"));
598 if (TC.
getTriple().isOSWindows() && needsUbsanRt()) {
601 CmdArgs.push_back(Args.MakeArgString(
605 Args.MakeArgString(
"--dependent-lib=" +
611 bool DiagnoseErrors) {
612 assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
613 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
614 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
615 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
616 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
617 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) &&
618 "Invalid argument in parseArgValues!");
620 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
621 const char *
Value = A->getValue(i);
624 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
625 0 == strcmp(
"all", Value))
632 else if (DiagnoseErrors)
633 D.
Diag(clang::diag::err_drv_unsupported_option_argument)
634 << A->getOption().getName() <<
Value;
640 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
641 A->getOption().matches(options::OPT_fno_sanitize_coverage));
643 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
644 const char *
Value = A->getValue(i);
645 int F = llvm::StringSwitch<int>(
Value)
655 D.
Diag(clang::diag::err_drv_unsupported_option_argument)
656 << A->getOption().getName() <<
Value;
664 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
667 const auto *Arg = *I;
668 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
673 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
676 Mask &= ~RemoveKinds;
679 llvm_unreachable(
"arg list didn't provide expected value");
683 assert(A->getOption().matches(options::OPT_fsanitize_EQ)
684 &&
"Invalid argument in describeSanitizerArg!");
686 std::string Sanitizers;
687 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
691 if (!Sanitizers.empty())
693 Sanitizers += A->getValue(i);
697 assert(!Sanitizers.empty() &&
"arg didn't provide expected value");
698 return "-fsanitize=" + Sanitizers;
DiagnosticBuilder Diag(unsigned DiagID) const
bool CCCIsCXX() const
Whether the driver should follow g++ like behavior.
Defines the clang::SanitizerKind enum.
static std::string toString(const clang::SanitizerSet &Sanitizers)
SanitizerMask Mask
Bitmask of enabled sanitizers.
bool IsUsingLTO(const llvm::opt::ArgList &Args) const
static SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A, bool DiagnoseErrors)
static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A)
std::unique_ptr< DiagnosticConsumer > create(StringRef OutputFile, DiagnosticOptions *Diags, bool MergeChildRecords=false)
Returns a DiagnosticConsumer that serializes diagnostics to a bitcode file.
SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups)
static SanitizerMask setGroupBits(SanitizerMask Kinds)
bool isCXX(ID Id)
isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers).
static bool getDefaultBlacklist(const Driver &D, SanitizerMask Kinds, std::string &BLPath)
SanitizerMask expandSanitizerGroups(SanitizerMask Kinds)
static SanitizerMask parseSanitizeTrapArgs(const Driver &D, const llvm::opt::ArgList &Args)
static std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask)
static std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args, SanitizerMask Mask)
std::string ResourceDir
The path to the compiler resource directory.